mysql高并发读写的核心瓶颈在于连接、锁、索引、事务隔离级别四层叠加后的实际争用,如rr级别下select...for update可能触发间隙锁导致阻塞,需通过读写分离、连接池限流、索引优化及小事务拆分等手段综合治理。

MySQL 高并发读写的核心瓶颈在哪
不是配置调得越高越好,而是连接、锁、索引、事务隔离级别这四层叠加后的真实争用。比如 SELECT ... FOR UPDATE 在 RR 隔离级别下可能触发间隙锁,一个慢查询就能让整段索引范围被堵住,其他读写全卡在等待锁上。
常见现象包括:show processlist 里大量 Locked 或 Waiting for table metadata lock;SHOW ENGINE INNODB STATUS 中 TRANSACTIONS 段显示大量 lock wait。
读多写少场景优先用读写分离 + 连接池
主库专注写入,从库分担查询压力,但要注意延迟和一致性边界。应用层不能假设从库“实时可见”刚写入的数据。
- 用
mysql-router或ProxySQL做自动路由,避免硬编码主从地址 - 应用连接池(如 HikariCP)最大连接数别设过高,
maxPoolSize建议控制在 20–50,配合connectionTimeout和idleTimeout防止连接堆积 - 显式标注只读语句:JDBC URL 加
readOnly=true,或 MyBatis 里用@Select+transactional(readOnly = true)
写密集场景必须拆分事务粒度 + 避免长事务
一个事务持续 2 秒以上,就很可能拖垮并发吞吐。尤其要警惕 ORM 自动生成的批量更新、带子查询的 UPDATE、没加 LIMIT 的 DELETE。
- 把大事务拆成小批次:例如删除千万级数据,用
DELETE FROM t WHERE id BETWEEN ? AND ? LIMIT 1000循环执行 - 写操作前先查再改?换成
INSERT ... ON DUPLICATE KEY UPDATE或REPLACE INTO,减少一次 SELECT + 一次 UPDATE 的往返和锁持有时间 - 业务允许时,用
INSERT IGNORE替代先查后插,避免唯一键冲突引发的死锁
索引失效和锁升级是并发性能隐形杀手
WHERE 条件没走索引、ORDER BY 引发 filesort、JOIN 字段类型不一致——这些都会让行锁升级为表锁或间隙锁,直接拉低并发能力。
- 用
EXPLAIN FORMAT=JSON看执行计划,重点关注key是否为NULL、type是否为ALL或index - 联合索引遵循最左匹配,
WHERE a = ? AND b > ? ORDER BY c要建(a, b, c),而不是(a, c, b) - 避免在索引字段上做函数操作:
WHERE DATE(create_time) = '2024-01-01'会丢弃索引,改用WHERE create_time >= '2024-01-01' AND create_time
真正难调的从来不是单条 SQL,而是多个业务模块共用同一张表、各自加锁逻辑互不感知时产生的锁竞争。上线前务必做真实流量镜像压测,而不是只跑 Sysbench。











