MySQL 高并发写入面试场景题

2次阅读

高并发写入应避免自增 ID 瓶颈,改用 UUID 或雪花算法;批量插入控制 500~2000 行并显式事务;用 INSERT 替代 UPDATE、冷热分离、延迟合并优化写扩散;调优 Buffer Pool、Redo Log 及 SSD 配置。

MySQL 高并发写入面试场景题

高并发写入场景下主键设计要避免自增 ID 瓶颈

在秒杀、抢券、日志采集等高频写入场景中,单机自增主键会成为性能瓶颈。InnoDB 的自增锁(AUTO-INC Lock)是表级锁,在高并发 INSERT 时会导致线程排队等待,吞吐量骤降。

建议方案:

  • 使用 UUID(短格式)或雪花算法(Snowflake)生成分布式唯一 ID,规避自增锁;注意 UUID 无序性对 B + 树插入性能的影响,可考虑用UUID_SHORT() 或将时间戳前置的有序 UUID
  • 若仍用自增,可配合innodb_autoinc_lock_mode = 2(交错模式)(需 binlog_format=ROW),大幅降低锁冲突,但要注意主从复制安全性
  • 分库分表时,主键应含分片字段(如 user_id % 4),避免全局唯一 ID 中心化依赖

批量写入必须绕过单条 INSERT 的开销

面试常问:“每秒 1 万订单怎么写入?”答“用 INSERT INTO … VALUES (…),(…),…”只是起点,真正关键在控制粒度与事务边界。

实操要点:

  • 单次批量行数建议500~2000 行:太少则网络 / 解析开销占比高;太多易触发 max_allowed_packet 限制或长事务阻塞
  • 显式控制事务:BEGIN; 多个 INSERT; COMMIT;,避免默认自动提交带来的频繁刷盘(innodb_flush_log_at_trx_commit= 1 时尤为明显)
  • 禁用唯一索引 / 外键校验(仅限导入期):SET unique_checks=0; SET foreign_key_checks=0;,导入完成后再恢复

写扩散问题:避免高频 UPDATE 引发的连锁反应

高并发场景下,看似简单的 UPDATE 可能隐含巨大代价——比如“库存扣减”触发二级索引更新、MVCC 版本链膨胀、Buffer Pool 压力激增。

优化思路:

  • 用 INSERT 替代 UPDATE:例如记录库存变更流水表(item_id, delta, ts),再异步聚合计算最终值,变“行锁竞争”为“顺序追加”
  • 冷热分离:高频更新字段(如 view_count、like_count)单独建宽表,与主体信息表解耦,减少主表 UPDATE 频率
  • 延迟合并:对非强实时场景(如排行榜分数),先写入 Redis 计数器,定时批量同步到 MySQL,避开写高峰

硬件与配置不调优,再好的 SQL 也白搭

面试官常追问:“你们线上怎么扛住 5000 QPS 写入?”答案不能只谈 SQL,要体现系统级意识。

  • innodb_buffer_pool_size设为物理内存的 70%~80%,确保热点数据常驻内存,减少磁盘随机写
  • innodb_log_file_size × 2 ≥ 1 小时峰值写入量,避免频繁 checkpoint 导致 I / O 抖动
  • SSD 是硬性要求,HDD 在高并发写入下 IOPS 瓶颈明显;同时启用 innodb_flush_method=O_DIRECT 绕过 OS 缓存,防止双缓存放大写放大
text=ZqhQzanResources