为什么IX-lock与InnoDB中的另一个IX-lock兼容?

时间:2014-09-18 03:34:47

标签: mysql locking innodb

根据innodb lock mode 锁定类型兼容性矩阵

    X           IX          S           IS
X   Conflict    Conflict    Conflict    Conflict
IX  Conflict    Compatible  Conflict    Compatible
S   Conflict    Conflict    Compatible  Compatible
IS  Conflict    Compatible  Compatible  Compatible

IX与IX兼容,但事实是如果我们在会话1中通过select c1 from z where c1 = 1 for update获得一个IX锁,那么尝试通过select c1 from z where c1 = 1 for update获取IX将在会话2中被阻止,所以我认为他们不兼容。我在这里错过了什么吗?

接受答案后编辑:

SELECT ... FOR UPDATE在一个会话中阻塞SELECT ... FOR UPDATE在另一个会话中的原因是他们不仅要求表级别上的IX锁定而且还要求行级别上的X锁定。这完全是因为X锁定。

2 个答案:

答案 0 :(得分:12)

https://dev.mysql.com/doc/refman/5.6/en/innodb-lock-modes.html说:

  

因此,意图锁不会阻止除完整表请求之外的任何内容(例如,LOCK TABLES ... WRITE)。 IX和IS锁的主要目的是显示有人锁定一行,或者在表中锁定一行。

这意味着多个线程可以获取IX锁。这些锁位于表级,而不是行级。 IX锁意味着持有它的线程打算更新表中某处的某些行。 IX锁仅用于阻止全表操作。

如果你认为它是双向的,它可能会有所帮助 - 如果正在进行全表操作,那么该线程有一个阻止IX锁的表级锁。

DML操作必须首先获取IX锁,然后才能尝试行级锁。原因是您不希望在ALTER TABLE正在进行时允许DML,或者在其他线程已完成LOCK TABLES...WRITE时允许DML。

UPDATEDELETESELECT..FOR UPDATE等行级更改不会被IX锁定阻止。它们被其他行级更改或实际的完整表锁(LOCK TABLES或某些DDL语句)阻止。但是除了那些表操作之外,运行DML的多个线程可能同时工作,只要它们各自处理一组不重叠的行。


重新评论:

第二个SELECT...FOR UPDATE没有被阻塞等待IX锁,它被阻塞等待已经被另一个线程中的X锁锁定的行上的X(行级)锁。 / p>

我刚试过这个,然后我跑了SHOW ENGINE INNODB STATUS所以我可以看到被阻止的交易:

---TRANSACTION 71568, ACTIVE 12 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 10, OS thread handle 140168480220928, query id 288 localhost root statistics
select * from test where id=1 for update
------- TRX HAS BEEN WAITING 12 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 802 page no 3 n bits 72 index `PRIMARY` of table `test`.`test` 
trx id 71568 lock_mode X locks rec but not gap waiting

请参阅?它表示它正在等待在表test主键索引上使用lock_mode X授予锁定。这是一个行级锁定。


让您对LOCK IN SHARE MODE

感到困惑

您正在谈论SELECT三个级别。

  • SELECT请求无锁。没有锁阻止它,它不会阻止其他锁。
  • SELECT ... LOCK IN SHARE MODE请求对表执行IS锁定,然后S锁定与索引扫描匹配的行。多个线程可以在表上保存IS锁或IX锁。多个线程可以同时保存S锁。
  • SELECT ... FOR UPDATE请求对表执行IX锁定,然后X锁定与索引扫描匹配的行。 X锁是独占,这意味着他们可以在任何其他线程上将X锁定锁定在同一行上。

但X和S锁都不关心IX或IS锁。

想想这个比喻:想象一下博物馆。

许多人,包括访客和策展人,都进入博物馆。参观者想要观看绘画,因此他们佩戴了标有“#34; IS"”的徽章。策展人可能会更换油画,因此他们会佩戴一张标有" IX"的徽章。博物馆里可以同时有很多人,有两种类型的徽章。他们不会互相阻挡。

在他们访问期间,严肃的艺术爱好者将尽可能地接近绘画,并研究它很长一段时间。在同一幅画之前,他们很乐意让其他艺术爱好者站在他们旁边。因此他们正在做SELECT ... LOCK IN SHARE MODE他们有" S"锁定因为他们至少不希望在他们研究它时更换它。

策展人可以取代一幅画,但他们对严肃的艺术爱好者很有礼貌,他们会等到这些观众完成并继续前进。所以他们正在尝试SELECT ... FOR UPDATE(或者只是UPDATEDELETE)。他们将获得" X"锁定在这个时候,通过挂一点注册说"展示被重新设计。"严肃的艺术爱好者希望以适当的方式呈现艺术,具有良好的灯光和一些描述性的匾额。他们等待重新设计在他们接近之前完成(如果他们尝试,他们会等待锁定。)

此外,你可能已经进入了一个博物馆,那里有更多的随意游客,试图远离其他人的方式。他们看着房间中间的画作,而不是接近太近。他们可以看到其他观众正在看的同样的画作,他们可以偷看严肃艺术爱好者的肩膀,看看那些被观看的画作。当他们更换画作时,他们甚至可能会对策展人嗤之以鼻(如果他们瞥见一幅尚未正确安装和点亮的画作,他们也不会在乎)。因此,这些随意的访客不会阻止任何人,也没有人阻止他们的观看。他们正在做SELECT并且他们不会要求任何锁定。

但也有建筑工人应该拆除墙壁和东西,但他们在建筑物内的任何人都不会工作。他们会等待每个人离开,一旦他们开始工作,他们就不会让任何人进入。这就是IS和IX徽章的存在如何阻止DDL(建筑工作),反之亦然。

答案 1 :(得分:0)

  

IS和IX锁允许多个客户端访问。在尝试在同一行上获得真正的锁之前,它们不一定会发生冲突。

     

但是表锁(ALTER TABLE,DROP TABLE,LOCK TABLES)阻塞了IS和IX,反之亦然。

因此IX-lock与另一个IX-lock兼容(它们都是表级)或IX-lock与另一个X-lock冲突(表级别不是行级别)

参考:http://www.slideshare.net/billkarwin/innodb-locking-explained-with-stick-figures