MySQL 锁超时问题的全链路定位与优化实践
1、问题 线上出现很多添加 key 锁超时的 mysql 日志。 https://apm.example.com/app/apm/services/<service_name>/transactions/view?rangeFrom=now-24h%2Fh&rangeTo=now&environment=&transactionName=%23 2、排查 1)查看 APM,发现了一个耗时的请求/sync,做语料同步的。后面插入语料 key 都显Lock wait timeout exceeded。 2)查看同步请求的具体链路,发现有多次批量 INSERT 操作,而且每次批量插入消耗的时间会逐步增加。最终也是执行成功的,花了24 分钟。后面其他事务的 Insert 操作都给阻塞住了。 3)查看锁日志,可以发现并不是死锁,而是普通的锁等待,最开始的批量操作(/sync)占用了大量的锁 4253982 row locks。后面的insert(添加 key)申请插入意向锁都被阻塞,等待一段时间之后上报超时错误给应用。 LOCK WAIT 8 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id <tid_1>, OS thread handle <handle_1>, query id <qid_1> <private-ip> <db_name> update INSERT INTO multilingual_item (item_id, corpus_id, lang, customize,`key`,value, description) VALUES (1001, 2001, 'xx-XX', 'default', 'key_1', '<text>', ''); ------- TRX HAS BEEN WAITING 22 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 345 page no 83690 n bits 136 index PRIMARY of table `<db_name>`.`multilingual_item` trx id <trx_waiting> lock_mode X insert intention waiting Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;; ------------------ ---TRANSACTION <trx_long>, ACTIVE 1166 sec starting index read mysql tables in use 1, locked 1 102372 lock struct(s), heap size 10379472, 4253982 row lock(s), undo log entries 943 MySQL thread id <tid_long>, OS thread handle <handle_long>, query id <qid_long> <private-ip> <db_name> update INSERT INTO multilingual_item (item_id, corpus_id, lang, customize,`key`,value, status, type) VALUES (2001, 3001, 'xx-XX', 'default', 'k1', 'v1', 2, 1), (2002, 3001, 'xx-XX', 'default', 'k2', 'v2', 2, 1); 4)查看代码,发现了调用 importJsonCorpus 进行多次批量操作,这跟 APM 看到的现象一致。这个方法上有事务注解,importJsonCorpus 方法的调用都在一个事务里,所以一次批量操作结束之后并不会释放锁。 ...