gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 06:40:07 26 4
gpt4 key购买 nike

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


在 session 1中,尝试通过获取 IX

select c1 from z where c1 = 1 for update


将在 session 2中被阻止,因此我认为它们不兼容。我在这里想念什么吗?

最终解释:
之所以

select ... for update


在一个 session 块中

select ... for update


另外一个问题是,他们不仅在表级别要求 IX锁定,还在行级别要求 X锁定。都是因为 X锁定。

最佳答案

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

Thus, intention locks do not block anything except full table requests (for example, LOCK TABLES ... WRITE). The main purpose of IX and IS locks is to show that someone is locking a row, or going to lock a row in the table.



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

如果您认为这是双向的,则可能会有所启发-如果正在进行全表操作,则该线程具有表级锁,该锁将阻止IX锁。

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

IX锁不会阻止像 UPDATEDELETESELECT..FOR UPDATE这样的行级更改。它们被其他行级更改或实际的完整表锁( 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而他们不要求任何锁。

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

    关于mysql - 为什么IX锁与InnoDB中的另一个IX锁兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25903764/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com