高并发下MySQL的真实瓶颈是连接、锁、索引、事务隔离级别四层叠加导致的争用;如REPEATABLE READ下SELECT...FOR UPDATE触发间隙锁,使后续读写卡在Waiting for lock状态。

高并发下 MySQL 的真实瓶颈在哪
不是 CPU 不够快,也不是磁盘不够新,而是连接、锁、索引、事务隔离级别这四层叠加后产生的实际争用。比如 SELECT ... FOR UPDATE 在 REPEATABLE READ 隔离级别下会触发间隙锁,一个慢查询就能把整段索引范围锁死,后续所有读写都卡在 Waiting for lock 状态。
常见信号包括:SHOW PROCESSLIST 里大量出现 Locked 或 Waiting for table metadata lock;SHOW ENGINE INNODB STATUS 中 TRANSACTIONS 段显示多个 lock wait。
读多写少时怎么避免主库被拖垮
主库只做写,从库分担读——但不能假设从库“实时可见”。应用层必须接受几秒甚至几十秒的复制延迟,尤其在主从切换或大事务同步时。
- 用
mysql-router或ProxySQL做自动路由,别在代码里硬编码jdbc:mysql://master:3306和jdbc:mysql://slave:3306 - JDBC URL 加
readOnly=true,或 MyBatis 方法上加@Transactional(readOnly = true),让中间件识别只读意图 - HikariCP 的
maxPoolSize控制在 20–50,配合connectionTimeout=3000和idleTimeout=600000,防止连接堆积成雪球
写密集场景下事务为什么一卡就全卡
事务持续超过 2 秒,就极大概率成为并发瓶颈。ORM 自动生成的批量 UPDATE、带子查询的 DELETE、没加 LIMIT 的清理语句,都是隐形杀手。
- 千万级数据删除,改用
DELETE FROM t WHERE id BETWEEN ? AND ? LIMIT 1000循环执行,每次提交后释放锁 - 避免“先
SELECT再UPDATE”,换成INSERT ... ON DUPLICATE KEY UPDATE或REPLACE INTO - 业务允许唯一键冲突时,用
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,而是多个业务模块共用一张表、各自加锁逻辑互不感知时产生的锁竞争——这时候光看慢日志没用,得结合 INFORMATION_SCHEMA.INNODB_TRX 和 INNODB_LOCK_WAITS 追源头。


















