监控告警有锁等待,查 data_locks 能看到 LOCK_WAIT,但按 ENGINE_TRANSACTION_ID 去 innodb_trx 里查是空的,排查断了。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
SELECT ENGINE_TRANSACTION_ID, THREAD_ID, OBJECT_NAME, LOCK_STATUS, LOCK_DATA FROM performance_schema.data_locks WHERE LOCK_STATUS = 'GRANTED'; SELECT THREAD_ID, PROCESSLIST_ID, PROCESSLIST_INFO FROM performance_schema.threads;
data_locks 里的等待记录属于还没拿到锁的请求,真正持锁的事务可能已经提交,锁只是还没被清理。另一个常见原因是账号权限不够,performance_schema 里部分表读不到。这一点先确认清楚,后面就不用反复试。
「锁持有者排查」这类改动最怕改一半,回滚脚本先准备好,再动生产。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
偶发问题先统计频率,一小时几次和一天一次,查法完全不同。
具体做法是,先看 data_locks 里 LOCK_STATUS 是 GRANTED 的那条;用 OWNER_THREAD_ID 去 threads 表拿 PROCESSLIST_ID;再按这个 id 去 processlist 里找具体 SQL;确认账号有 performance_schema 的查询权限。
改完照着核一遍,能顺着线程找到持锁的 SQL 和连接来源 锁等待不再无处下手。
