用好innodb行级锁需确保走索引,避免全表锁;调低隔离级别至read committed可关闭间隙锁;批量操作用多值sql或load data infile;连接池与wait_timeout需合理匹配。

用好 InnoDB 的行级锁而不是默认用表锁
MySQL 默认的 MyISAM 引擎只支持表级锁,一写全堵;InnoDB 才真正支持行级锁,但前提是必须走索引。如果 UPDATE 或 SELECT ... FOR UPDATE 语句没命中索引,InnoDB 会退化为锁整张表——这是并发骤降最常见原因。
- 检查执行计划:对关键 DML 语句运行
EXPLAIN,确认type是ref/range而非ALL - 避免在 WHERE 条件里对索引列做函数操作,比如
WHERE YEAR(create_time) = 2024会让索引失效 - 主键或唯一索引上的等值查询(
WHERE id = ?)才能保证精确到单行锁;范围查询(WHERE id > 100)可能锁住间隙,需结合SELECT ... LOCK IN SHARE MODE或事务隔离级别权衡
调低事务隔离级别,别死守 REPEATABLE READ
InnoDB 默认隔离级别是 REPEATABLE READ,它靠多版本并发控制(MVCC)+ 间隙锁(Gap Lock)来防止幻读,但间隙锁会显著增加锁冲突概率,尤其在高并发 INSERT 场景下容易卡住。
- 如果业务能接受「不可重复读」,把隔离级别设为
READ COMMITTED:关闭间隙锁,MVCC 版本链只保留已提交版本,大幅减少锁等待 - 设置方式:连接级用
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;全局可在配置文件加transaction_isolation = 'READ-COMMITTED' - 注意:
READ COMMITTED下,同一个事务中多次SELECT可能读到不同结果,需前端逻辑兜底
批量操作别用循环单条 INSERT/UPDATE
每条语句都走一次网络往返 + 事务开销 + 行锁获取,在并发写入时极易形成锁队列瓶颈。哪怕只是 100 条数据,逐条执行可能比批量插入慢 5–10 倍。
- 改用
INSERT INTO ... VALUES (...), (...), (...)多值语法,单语句插入最多 1000 行(受max_allowed_packet限制) - 更新场景优先考虑
INSERT ... ON DUPLICATE KEY UPDATE或REPLACE INTO,避免先查后更的两阶段锁 - 超大批量(如 > 10 万行)用
LOAD DATA INFILE,它绕过 SQL 解析层,直接写入存储引擎,吞吐量提升一个数量级
连接池大小和 wait_timeout 要匹配实际负载
应用端连接池(如 HikariCP)最大连接数设太高,MySQL 的 max_connections 没跟上,会导致连接拒绝;设太低又让请求排队。更隐蔽的问题是 wait_timeout 过长,空闲连接占着不放,把可用连接数悄悄耗尽。
- 观察指标:
SHOW STATUS LIKE 'Threads_connected'和SHOW STATUS LIKE 'Threads_running',前者持续接近max_connections就说明要扩容或优化 -
wait_timeout建议设为 60–180 秒(应用连接池的 idleTimeout 应略小于此值),避免连接僵死 - 连接池的
maxLifetime要小于wait_timeout,否则连接被 MySQL 主动断开后,应用端还试图复用,抛出Connection reset或Lost connection










