MST

星途 面试题库

面试题:MySQL Schema设计在高并发场景下的陷阱与应对策略

在高并发场景下,MySQL Schema设计可能面临锁争用、数据热点等陷阱。请结合实际项目经验,深入分析这些陷阱产生的原因,并提出全面且具有针对性的避免方法,涵盖从表结构优化、事务处理到缓存策略等多个层面。
39.5万 热度难度
数据库MySQL

知识考点

AI 面试

面试题答案

一键面试

锁争用陷阱

  1. 产生原因
    • 行锁粒度问题:如果索引设计不合理,行锁可能会升级为表锁,导致大量事务等待锁释放,例如在查询时使用了非索引字段作为条件,MySQL无法精准定位行,只能锁住整个表。
    • 事务隔离级别:较高的隔离级别(如可串行化)会增加锁的范围和持有时间。例如在可串行化隔离级别下,事务在读取数据时会对数据加锁,防止其他事务修改,这在高并发场景下容易造成锁争用。
    • 死锁:多个事务互相等待对方释放锁,形成死循环。比如事务A持有资源1的锁并请求资源2的锁,而事务B持有资源2的锁并请求资源1的锁。
  2. 避免方法
    • 优化索引:确保经常用于查询条件、连接条件的字段上有合适的索引。例如在电商订单表中,经常根据订单号查询订单详情,订单号字段应建立索引,这样可以减少锁的粒度,使MySQL能精确锁定行。
    • 合理选择事务隔离级别:根据业务需求选择合适的隔离级别。对于读多写少的场景,可以选择读提交(Read Committed)或可重复读(Repeatable Read)隔离级别,减少锁的持有时间。例如在新闻资讯类网站,对新闻内容的读取操作多,写操作少,可以使用读提交隔离级别。
    • 死锁检测与超时设置:MySQL有死锁检测机制,当检测到死锁时,会自动回滚其中一个事务来打破死锁。同时,可以设置合理的事务等待锁超时时间,避免事务无限期等待。

数据热点陷阱

  1. 产生原因
    • 热门数据集中访问:某些数据在高并发场景下被频繁访问,例如电商大促活动时,热门商品的库存数据被大量订单同时查询和修改,导致该数据成为热点。
    • 数据分布不均匀:表结构设计不合理,数据没有均匀分布在各个分区或节点上。比如按照时间戳对数据进行分区,但时间分布集中在某一时间段,导致该分区成为热点。
  2. 避免方法
    • 数据缓存:在应用层使用缓存(如Redis)来缓存热门数据。例如将热门商品的库存信息缓存在Redis中,高并发请求先从Redis读取和修改库存,然后再批量同步到MySQL,减少对MySQL的直接压力。
    • 数据分区与分表:根据业务特点进行合理的分区和分表。如按照地区对用户表进行分区,不同地区的用户数据存储在不同的分区中,避免单个分区成为热点。对于订单表,可以按照订单时间进行分表,减少数据热点。
    • 读写分离:采用主从复制架构,主库负责写操作,从库负责读操作。将读请求分发到从库,减轻主库压力。例如在社交媒体平台,大量的读请求(如查看用户动态)可以由从库处理,主库专注于写操作(如发布新动态)。

表结构优化

  1. 字段设计
    • 尽量使用固定长度字段:例如使用CHAR代替VARCHAR,这样可以减少存储碎片,提高查询效率。在用户性别字段上,固定长度的CHAR(1) 就足以存储 “男” 或 “女”。
    • 避免使用大字段:如TEXT、BLOB等大字段,如果必须使用,可以考虑将大字段独立存储在其他表中,通过外键关联,减少主表数据量。
  2. 范式与反范式
    • 适度反范式:在满足业务需求的前提下,为了减少表连接操作,可以适度采用反范式设计。例如在订单表中冗余一些用户信息(如用户名、联系方式),避免每次查询订单都要连接用户表。

事务处理

  1. 减少事务粒度:将大事务拆分成多个小事务。例如在电商订单处理中,下单、支付、发货等操作可以拆分成不同的事务,减少事务持有锁的时间。
  2. 按相同顺序访问资源:多个事务对资源的访问顺序保持一致,避免死锁。例如在涉及多个账户资金转移的事务中,所有事务都按照账户ID从小到大的顺序获取锁。

缓存策略

  1. 缓存更新策略:采用合适的缓存更新策略,如写后失效(Write - Behind)、写前失效(Write - Ahead)或双写策略。写后失效是在更新数据库后失效缓存,简单但可能存在缓存与数据库不一致的短暂时间;写前失效是在更新数据库前失效缓存;双写策略是同时更新数据库和缓存,保证数据一致性但性能略低。
  2. 缓存预热:在系统启动时,将热门数据预先加载到缓存中,避免高并发时缓存击穿问题。例如在电商系统启动时,将热门商品信息加载到Redis缓存中。