【问题标题】:Why is an IX-lock compatible with another IX-lock in InnoDB?为什么 IX 锁与 InnoDB 中的另一个 IX 锁兼容?
【发布时间】:2014-11-12 06:26:44
【问题描述】:

根据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

IXIX 兼容,但事实是如果我们获得一个IX

select c1 from z where c1 = 1 for update

在会话 1 中,尝试通过

获取IX

select c1 from z where c1 = 1 for update

将在会话 2 中被阻止,所以我认为它们不兼容。我错过了什么吗?


最终解释:

原因

select ... for update

在一个会话块中

select ... for update

另一方面,他们不仅要求IX 锁定表级别,还要求X 锁定行级别。都是因为X锁。

【问题讨论】:

    标签: mysql locking innodb


    【解决方案1】:

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

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

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

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

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

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


    你的评论:

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

    我刚刚尝试了这个,然后我运行了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 锁一个 S 锁。

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

    想想这个类比:想象一个博物馆。

    许多人,包括参观者和策展人,进入博物馆。参观者想看画,所以他们戴着标有“IS”的徽章。策展人可能会更换画作,因此他们会佩戴标有“IX”的徽章。博物馆里可以同时有很多人,同时持有两种类型的徽章。它们不会互相阻挡。

    在参观期间,认真的艺术爱好者将尽可能地靠近这幅画,并长时间研究它。他们很高兴让其他艺术爱好者在同一幅画前站在他们旁边。因此,他们正在做SELECT ... LOCK IN SHARE MODE 并且他们有“S”锁,因为他们至少不希望在他们研究这幅画时被替换。

    策展人可以更换一幅画,但他们对严肃的艺术爱好者很有礼貌,他们会等到这些观众看完后再继续前进。所以他们正在尝试做SELECT ... FOR UPDATE(或者只是UPDATEDELETE)。他们此时将获得“X”锁,挂一个小牌子,上面写着“展览正在重新设计”。严肃的艺术爱好者希望看到艺术以适当的方式呈现,有漂亮的灯光和一些描述性的牌匾。他们会在接近之前等待重新设计完成(如果他们尝试,他们会等待锁定)。

    另外,您可能去过一个博物馆,那里有更多休闲游客四处游荡,试图避开其他人。他们从房间中间看画,不要靠得太近。他们可以看其他观众正在看的同一幅画,他们可以从严肃的艺术迷的肩膀上偷看,也可以看到那些正在观看的画。他们甚至可能在更换画作时盯着策展人看(他们不在乎是否瞥见了尚未正确安装和照明的画作)。所以这些随便的访客不会屏蔽任何人,也没有人会屏蔽他们的观看。他们只是在做SELECT,他们不请求任何锁。

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

    【讨论】:

    • 你好 Bill,通过说“SELECT ... FOR UPDATE 未被 IX 锁阻塞”,那么如何解释 SELECT ... FOR UPDATE 被另一个 SELECT ... FOR UPDATE 阻塞确实是IX锁
    • 令人印象深刻,它正在等待 X 锁定,但是谁设置了 X 呢? SELECT ... FOR UPDATE 只问IX锁吧?
    • 否 -- SELECT...FOR UPDATE 锁定由索引扫描读取的行,就像您对这些行执行了 UPDATEDELETE 语句一样。请参阅dev.mysql.com/doc/refman/5.6/en/innodb-locking-reads.html 因此SELECT...FOR UPDATE 尝试创建 X 锁,如果这些行上已经存在其他 X 锁,则会被阻止。如果它获取锁,它会阻塞读取相同行的其他SELECT...FOR UPDATE 语句。
    • 再次感谢。这就是重点,也是我感到困惑的原因,因为根据 mysql refmanual SELECT ... FOR UPDATE 发出 IX 而不是 X,“例如,SELECT ... LOCK IN SHARE MODE 设置 IS 锁和 SELECT .. . FOR UPDATE 设置一个 IX 锁。” ref: dev.mysql.com/doc/refman/5.7/en/innodb-lock-modes.html,另外我怀疑是X锁,因为X锁与共享锁冲突,所以当有X锁时你不能发出select(没有FOR UPDATE),事实是你可以选择(没有FOR UPDATE)即使已经有 SELECT ... FOR UPDATE
    • 太棒了,IX锁是表级锁,我还以为是行级锁,你应该得到的不仅仅是50分,我希望我能提供更多,谢谢
    【解决方案2】:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-26
      • 1970-01-01
      • 2023-03-09
      • 2019-08-20
      • 1970-01-01
      相关资源
      最近更新 更多