已采纳
回答正文
回复
讨论正文
该问题的正文、回答与讨论。
背景
主库 MySQL 8.0.32 / InnoDB,单主单从,innodb_buffer_pool_size=64G、innodb_purge_threads=4、innodb_deadlock_detect=ON、innodb_lock_wait_timeout=50、隔离级别 RR。核心表 t_settle_record 约 3.2 亿行,二级索引 idx_uid_status (uid, status, create_time)。白天 OLTP 高频点查/更新同一索引区间,QPS 约 1800(读写比 7:3),P99 基线 2–4ms。
凌晨 02:00 起有一个对账修复任务:单事务里按 uid 范围执行约 200 万条 UPDATE t_settle_record SET status='reconciled' WHERE uid=? AND status='pending',事务已运行 40+ 分钟未提交。期间出现三件事同时发生:
SELECT ... WHERE uid=? AND status=?)P99 从 2ms 涨到 15–20ms;UPDATE 开始报 Lock wait timeout exceeded(50s);SHOW ENGINE INNODB STATUS 里 History list length 从 0 涨到约 30 万。已排查到的现状
information_schema.innodb_trx:该事务 trx_state=RUNNING、trx_started 距 now 40+ 分钟、trx_rows_modified 已 200 万+、trx_rows_locked 200 万+(数字与 rows_modified 基本一致,怀疑是 record lock 为主);performance_schema.data_locks:该事务持锁记录里 LOCK_MODE 以 X,REC_NOT_GAP 为主,夹杂少量 X,GAP(RR 下正常);卡点与想问的具体问题
trx_started 距 now 超过 N 分钟、trx_rows_modified 增速归零、还是 data_locks 里锁模式/锁对象范围?有没有一套可执行、可写成监控告警的判断口径(比如「trx_rows_modified 连续 5 分钟不再增长 + trx_rows_locked > 100 万 → 告警」)?innodb_lock_wait_timeout 临时调短 + 应用侧加退避重试,让新请求先走,再 KILL 持锁方)?UPDATE ... WHERE uid=? AND status=? 走 idx_uid_status 时,RR 下到底锁了哪些 gap?如果该 uid 下 status='pending' 的行很少(比如 5 行),但 status='reconciled' 的行很多(比如 5000 行),会不会因为 gap lock 把后面不相干的区间也锁住,导致其他 uid 的 UPDATE 也被卡住?(我目前从 data_locks 看主要是 X,REC_NOT_GAP,但不确定 gap 部分是否还有隐性影响)期望得到的答案形态
information_schema / performance_schema 的具体查询语句;相关参考(站内已读)