
MySQL锁等待实战排查2条SQL快速锁定肇事者【免费下载链接】CS-Base图解计算机网络、操作系统、计算机组成、数据库共 1000 张图 50 万字破除晦涩难懂的计算机基础知识让天下没有难懂的八股文 在线阅读https://xiaolincoding.com项目地址: https://gitcode.com/GitHub_Trending/cs/CS-Base凌晨2点业务同事冲了进来结算接口转了10分钟。先别慌着重启这种「越干越堵」的症状多是MySQL锁等待造成的。照这套做自查排除、两句SQL取证、死锁日志审讯就能说清谁卡了谁、安全解堵。⚠️ 别急着查锁3个自问排除「假锁等待」碰到锁相关表之前先自问三句一半的「接口转圈」根本不是锁是「慢」还是「堵」单条SQL慢、加索引就变快那是慢SQL、执行计划的问题。真锁等待长这样一条平时毫秒级返回的SQL卡在同一条语句上SHOW PROCESSLIST 里它的 Time 一直涨、就是不结束。连接池是不是满了应用日志在刷「拿不到连接 / connection pool exhausted」时堵在应用侧。先核对连接池大小和max_connections数据库本身可能很闲。数据库里看没看到「等待」information_schema.innodb_trx里出现trx_state LOCK WAIT的事务才能坐实是锁等待再进入下一步取证。三问都指向否 → 回慢SQL或连接池那条线查第三问指向是 → 往下走。取证2条SQL摸清锁等待「谁等谁」坐实锁等待后只需要跑两条语句。第一条看谁在等、卡在哪句SQLSELECT * FROM information_schema.innodb_trx\G;重点看四列trx_state是 LOCK WAIT 还是 RUNNINGtrx_query是等待事务卡住的语句肇事者通常就在其中trx_mysql_thread_id是这个事务的连接id先抄下来后面 KILL 就靠它trx_started配trx_rows_locked判断是不是长事务、锁了多少行。拿到trx_id后还能和下一条命令里的引擎事务id互相印证。第二条看谁在等谁SELECT * FROM performance_schema.data_lock_waits\G;它直接输出「等待方 → 阻塞方」的配对REQUESTING_*是被卡住的BLOCKING_*是卡人的BLOCKING_THREAD_ID就是阻塞方的连接id。想确认阻塞方手里是什么锁再查performance_schema.data_locksLOCK_MODE为X, REC_NOT_GAP是记录锁X, GAP是间隙锁裸X是 Next-Key 锁LOCK_DATA给出锁范围的右边界。InnoDB死锁日志4步读法逐条审讯肇事者已经发生过死锁的话数据库留下过「案底」SHOW ENGINE INNODB STATUS\G;找到LATEST DETECTED DEADLOCK段像审讯嫌疑人一样问四遍谁在等找带WAITING FOR的事务它是被卡住的那个谁持锁等锁链条上的另一方它要的锁攥在对方手里各持了什么看各自的HOLDS THE LOCK(S)记下索引名、lock_modeX 还是 S、带不带 gap、锁数据当时在干什么看各自的最后一条SQL TEXT九成情况肇事语句就在这里——通常是两个事务以不同顺序写同一批行。读完就明白数据库已自动回滚了「更轻」的那个事务业务侧收到的是Deadlock found报错另一个事务解除阻塞后继续跑。日志的作用是交代「为什么」怎么防看下一节。现场处置KILL还是等症状→动作对照表别上来就 KILL先对症状选动作你看到什么做什么1~2个事务LOCK WAIT50秒内数据库锁等待超时默认值会自己超时先不动手看阻塞方的trx_query确认不是大事务超时会自行释放同一条语句的等待队列越排越长、业务已停滞KILL「队首」阻塞事务KILL 12345;12345 取trx_mysql_thread_id不是 trx_id队首回滚放锁后整队自然疏通不必逐个杀业务反复刷数据库锁等待超时的报错临时调小 innodb_lock_wait_timeout 设置SET GLOBAL innodb_lock_wait_timeout 10;快速失败、业务立刻重试防止队列越堆越长业务抛Deadlock found错误无需人工数据库已自动回滚其一业务侧补重试与幂等为什么杀队首而不是杀队列里的队里的事务只是干等杀了也只解决自己队首是锁的源头杀掉后所有等待事务一次解锁。✅ 防复发上线前3个检查项堵解开了还得把口子补上上线前逐条过索引每条带锁语义的语句update、delete、锁定读先 EXPLAIN 确认走索引扫描。全表扫描等于锁全表「update没带索引」这类事故可看 update没加索引会锁全表事务粒度事务里只放数据库操作做完立即提交涉及多个资源时保持固定访问顺序比如永远按 id 升序处理顺序一致就不会形成循环等待隔离级别业务不依赖防幻读就切到 READ COMMITTED间隙锁基本消失锁的范围从「一段区间」缩回「一行」。用类比说清默认「可重复读」级别下锁的范围有多大记录锁是「占座」直接坐死这一座间隙锁是「排队」人没坐但在空位上插了牌子、别人插不进来Next-Key 锁是「排队连空位一起占」人坐下、空位也插牌。READ COMMITTED 基本只做「占座」争端自然少。复盘库存扣减锁等待3行收场另一个同类案例链路很短现象——秒杀一开库存扣减接口持续报数据库锁等待超时根因——扣减语句走非唯一索引、扫描范围大两个事务各自锁住同一段间隙互相等待修复——扣减改为按主键单行 update隔离级别调成 READ COMMITTED效果——整场秒杀再无锁等待扣减成功率回到 99.9%。延伸阅读一句话收束先分清是不是真锁再用两条SQL坐实谁卡谁KILL队首解堵最后用索引、事务、隔离级别三件套防复发。MySQL 死锁了怎么办MySQL 是怎么加锁的【免费下载链接】CS-Base图解计算机网络、操作系统、计算机组成、数据库共 1000 张图 50 万字破除晦涩难懂的计算机基础知识让天下没有难懂的八股文 在线阅读https://xiaolincoding.com项目地址: https://gitcode.com/GitHub_Trending/cs/CS-Base创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考