不能只盯 innodb_row_lock_waits 绝对值,因其是自启动累计值、不反映实时压力、无法区分偶发抖动与持续高压,且高值可能由单个长事务导致;须结合 innodb_row_lock_current_waits(瞬时等待数)和 innodb_row_lock_time_avg(平均等待时长)综合判断锁争用真实状况。

innodb_row_lock_waits 单看数值本身没有意义,必须结合时间窗口和业务节奏判断是否“激烈”。
为什么不能只盯 innodb_row_lock_waits 的绝对值
这个值是自 MySQL 启动以来的累计总数,重启后归零。如果数据库跑了三个月,innodb_row_lock_waits 是 1200,平均每天才 13 次——可能完全正常;但如果过去 5 分钟就涨了 800,那基本可以断定正在发生严重争用。
- 它不反映当前压力,只记录历史发生过多少次等待
- 无法区分是偶发抖动还是持续高压
- 高值可能是由一次长事务拖累多个后续语句造成的,实际锁持有者只有一个
必须搭配 innodb_row_lock_current_waits 看瞬时状态
这才是判断“此刻是否卡住”的核心指标。只要它持续 > 5,就说明有真实阻塞正在发生,不是历史遗留问题。
-
innodb_row_lock_current_waits = 0:当前无等待,哪怕innodb_row_lock_waits是 10 万也不用紧急处理 -
innodb_row_lock_current_waits ≥ 10:需立即查performance_schema.data_lock_waits定位谁在等谁 - 注意:该值为 0 不代表没锁竞争,只是没形成“等待队列”(比如两个事务快速交替获取/释放同一行锁)
结合 innodb_row_lock_time_avg 判断影响程度
平均等待时长比等待次数更能说明问题。即使每分钟只等 2 次,但每次平均卡 200ms,对延迟敏感的服务(如支付、库存扣减)已经不可接受。
-
innodb_row_lock_time_avg > 50ms:索引或查询逻辑大概率有问题,需检查是否走了全表扫描或非最优索引 -
innodb_row_lock_time_max > 1000ms:存在明显异常事务,优先查INFORMATION_SCHEMA.INNODB_TRX中trx_state = 'LOCK WAIT'且trx_started很早的记录 - 该指标单位是毫秒,但注意它是“总锁等待时间 / 总等待次数”,受极值影响大,需配合
innodb_row_lock_time_max看分布
真正要盯的是变化率,不是快照值
监控系统里建议配置以下告警规则,而不是静态阈值:
- 过去 1 分钟内
innodb_row_lock_waits增量 ≥ 100 - 过去 30 秒内
innodb_row_lock_current_waits最大值 ≥ 8 -
innodb_row_lock_time_avg5 分钟滑动窗口环比上涨 300%
锁竞争的本质是资源争抢,而资源争抢一定表现为“短时间突增”。盯着一个不断累加的整数去拍板,就像靠总车祸数判断某路口是否拥堵一样不靠谱。


















