问个innodb死锁问题

[复制链接]
查看11 | 回复9 | 2011-11-1 16:20:28 | 显示全部楼层 |阅读模式
最近系统碰到一个死锁问题,虽然问题解决了,但是对innodb的锁还有一些疑问,想请教高人。
mysql reference上有一个死锁的简单例子:
有一张表t,CREATE TABLE t (i INT) ENGINE = InnoDB;
插入数据,INSERT INTO t (i) VALUES(1);
客户端A:
START TRANSACTION;
SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE; ----①
然后客户端B,START TRANSACTION;DELETE FROM t WHERE i = 1;-------②这时候阻塞,
然后再客户端A:DELETE FROM t WHERE i = 1;-----③这时候就会产生死锁,通过命令show innodb status查看,在上面执行第①条语句的时候,在t上有一个IS锁和这条记录上有个S锁,在第②条语句的时候第二个事务拥有对t的IX锁,等待X锁。我的问题是:1.死锁产生的原因是不是由于第二个事务拥有了IX锁,而不能得到X锁(由于第一个事务的S锁),而第一个事务也是要取得X锁,但由于第二个事务拥有了IX锁(IX和X冲突),所以产生死锁?2.在执行第②条语句的时候,为什么能个获得IX锁?因为我从手册上看S锁和IX锁是有冲突的,既然第一个事务已经取得了S锁,那么第二个事务为什么还能取得IX锁?
还望各位不吝赐教。

回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
e,,第二个事务需要的两个锁都没有获取到,(IX和X),这两个锁都在等
回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
死锁产生的原因:就是多个事务互相占用(即锁住了)对方需要的资源,等待且都不释放锁,导致产生死锁!

回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
jiwang1980 发表于 2011-12-19 09:48
e,,第二个事务需要的两个锁都没有获取到,(IX和X),这两个锁都在等

但是我开启innodb_lock_monitor以后,看到第二个事务以及取得了IX锁,等待X锁。
ABLE LOCK table `test`.`t` trx id 101411 lock mode IX
RECORD LOCKS space id 0 page no 29448 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`t` trx id 101411 lock_mode X waiting
回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
jiwang1980 发表于 2011-12-19 09:48
e,,第二个事务需要的两个锁都没有获取到,(IX和X),这两个锁都在等

死锁产生的条件我当然知道,不知道你有没有看我的问题,我的问题其实就是第二个事务到底占用了哪个资源导致死锁。
回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
winterroot 发表于 2011-12-19 12:44
但是我开启innodb_lock_monitor以后,看到第二个事务以及取得了IX锁,等待X锁。
ABLE LOCK table `test` ...

e,刚确认了一下,IS与IX是可以兼容的。我错了,所以第二个事务获得了IX锁,等待X锁
回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
winterroot 发表于 2011-12-19 12:45
死锁产生的条件我当然知道,不知道你有没有看我的问题,我的问题其实就是第二个事务到底占用了哪个资源导 ...

第二个事务并没有占什么资源,只是在等待第一个事务的锁释放,并且在表上又加了一个IX锁。死锁的根源在第一个事务的IS锁上
所以你在第一个是事务里执行了delete 操作时候,第一个事务又会对表加IX锁,这样就会第二个事务IX等待第一个事务结束,第一个事务由于IX锁等待第二个事务的IX锁,死锁产生了,系统检测会回滚第二个事务。

不知道对不对

回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
winterroot 发表于 2011-12-19 12:45
死锁产生的条件我当然知道,不知道你有没有看我的问题,我的问题其实就是第二个事务到底占用了哪个资源导 ...

第二个事务并没有占什么资源,只是在等待第一个事务的锁释放,并且在表上又加了一个IX锁。死锁的根源在第一个事务的IS锁上
所以你在第一个是事务里执行了delete 操作时候,第一个事务又会对表加IX锁,这样就会第二个事务IX等待第一个事务结束,第一个事务由于IX锁等待第二个事务的IX锁,死锁产生了,系统检测会回滚第二个事务。

不知道对不对

回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
本帖最后由 winterroot 于 2011-12-19 14:43 编辑
jiwang1980 发表于 2011-12-19 14:14
e,刚确认了一下,IS与IX是可以兼容的。我错了,所以第二个事务获得了IX锁,等待X锁

但是,第一个事务已经取得了S锁,而S锁和IX是不兼容的。这是怎么回事?是不是因为意向锁只是针对表锁的,对记录锁没关系?
回复

使用道具 举报

千问 | 2011-11-1 16:20:28 | 显示全部楼层
客户端A:
START TRANSACTION;
SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE; ----①
然后客户端B,START TRANSACTION;DELETE FROM t WHERE i = 1;-------②这时候阻塞,
然后再客户端A:DELETE FROM t WHERE i = 1;

客户端A:LOCK IN SHARE MODE 会加上 S锁,也即允许其他线程读,但是不能修改,也即可以再加S锁,但是不能修改
客户端B:DELETE FROM t WHERE i = 1; 将等待记录的写锁
客户端A:DELETE FROM t WHERE i = 1;将会成功获得写锁权利,因为该事务已经获得记录的S锁,所以事务内部升级锁是没问题的
客户端B:发现想加写锁的记录被删除了,那么也是属于死锁的一种无法成功加锁.
上述要注意事务的隔离级别,否则不同也是效果不一样的,测试是在RR模式下才可重现.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行