select for update引发死锁分析

问题复现

读写锁冲突

场景:4场直播同时准备作业。首先查询作业是否有这条记录。这里查询后添加写锁。


select for update引发死锁分析

作业准备前是没有记录的,所以这里就会造成间隙锁。

假设现在只有3条数据。然后通过role查询等于4的。这里查不到数据库,就会锁住3之后的所有数据。


select for update引发死锁分析

先营造测试环境,给xxl_job_user表role字段添加唯一索引。

执行如下命令:

set @@autocommit=0;

SHOW VARIABLES like ‘%autocommit%’;

START transaction ;

SELECT * FROM xxl_job_user where role =4 for update;


select for update引发死锁分析

这里就锁住了role>=4之后的所有数据。

但是另外的线程还是可以访问表的。

间隙锁在InnoDB的唯一作用就是防止其它事务的插入操作,以此来达到防止幻读的发生,所以间隙锁不分什么共享锁与排它锁。

但是,在这时插入role=4的就会阻塞。


select for update引发死锁分析

特别注意:

因为是间隙锁,假设我现在插入一条数据,role=8;


select for update引发死锁分析

在这里执行一条sql,插入role>8的就会被成功。因为这里间隙锁只会在4-8之间生效。


select for update引发死锁分析

相关排查指令

#查看当前在锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

#查看当前锁定的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

#查看当前等锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

show OPEN TABLES where In_use > 0;

SHOW ENGINE INNODB STATUS


select for update引发死锁分析

解决方法

1:杀死进程id(就是 SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX; 命令的trx_mysql_thread_id列)

kill 线程ID

2:引入分布式锁解决。

3:修改事务隔离策略。(没用)

这样间隙锁就失效了,从而升级为表锁。会阻塞所有的请求。

show variables like ‘tx_isolation’;

SET session TRANSACTION ISOLATION LEVEL Read committed;


select for update引发死锁分析

还是会阻塞


select for update引发死锁分析

SET session TRANSACTION ISOLATION LEVEL Repeatable read;

死锁   select   for
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章