关于mysql:手把手教你定位线上MySQL锁超时问题包教包会

37次阅读

共计 1356 个字符,预计需要花费 4 分钟才能阅读完成。

发现有 MySQL 锁超时的谬误日志。

不必想,必定有另一个事务正在批改这条订单,持有这条订单的锁。

导致以后事务获取不到锁,始终期待,直到超过锁超时工夫,而后报错。

既然问题曾经分明了,接下来就轮到怎么排查一下到底是哪个事务正在持有这条订单的锁。

好在 MySQL 提供了丰盛的工具,帮忙咱们排查锁竞争问题。

现场复现一个这个问题:

创立一张用户表,造点数据:

CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
  `name` varchar(50) NOT NULL DEFAULT ''COMMENT' 姓名 ',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

事务 1,更新 id= 1 的用户姓名,不提交事务:

begin;
update user set name='一灯' where id=1;

事务 2,删除 id= 1 的数据,这时候会产生锁期待:

begin;
delete from user where id=1;

接下来,咱们就通过 MySQL 提供的锁竞争统计表,排查一下锁期待问题:

先查一下锁期待状况:

select * from information_schema.innodb_lock_waits;

能够看到有一个锁期待的事务。

而后再查一下正在竞争的锁有哪些?

select * from information_schema.innodb_locks;

能够看到,MySQL 统计的十分具体:

lock_trx_id 示意事务 ID

lock_mode 示意排它锁还是共享锁

lock_type 示意锁定的记录,还是范畴

lock_table 锁的表名

lock_index 锁定的是主键索引

再查一下正在执行的事务有哪些?

select * from information_schema.innodb_trx; 

能够分明的看到正在执行的事务有两个,一个状态是锁期待(LOCK WAIT),正在执行的 SQL 也打印进去了:

delete from user where id=1;

正是事务 2 的删除语句。

不必问,第二条,显示正在运行状态(RUNNING)的事务就是正在持有锁的事务 1,MySQL 线程 id(trx_mysql_thread_id)是 193。

咱们用 MySQL 线程 id 查一下事务线程 id:

select * from performance_schema.threads where processlist_id=193;

找到对应的事务线程 id 是 218,而后再找一下这个线程正在执行的 SQL 语句:

select THREAD_ID,CURRENT_SCHEMA,SQL_TEXT 
from performance_schema.events_statements_current 
where thread_id=218;

能够分明的看到这个线程正在执行的 SQL 语句就是事务 1 的 update 语句。

持有锁的 SQL 语句找到了,接下来再去找对应的业务代码也就轻而易举了。

以上是基于 MySQL5.7 版本,在 MySQL8.0 版本中有些命令曾经删除了,替换成了其余命令,下篇文章再讲一下 MySQL8.0 怎么定位 MySQL 锁超时问题。感兴趣的小伙伴能够本人再虚拟机上部署一套零碎本人尝试以下, 博主比拟罕用的就是 3A 云服务器。

正文完
 0