Irf*_*mad 6 mysql innodb rowlocking
我在一个表中有5行(1到5)。我要锁定第2行以进行一些更新,与此同时,如果有人尝试更新第4行,那么他应该可以更新。
我正在下面的代码中尝试此操作,但是我觉得它将锁定放在表级别而不是行级别。
------第一场
START TRANSACTION;
SELECT * FROM test WHERE t=1 FOR UPDATE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
-----会话2(已被阻止)
START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
代替FOR UPDATE使用LOCK IN SHARE MODE。FOR UPDATE防止其他事务也读取该行。LOCK IN SHARE MODE允许读取,但禁止更新。
参考:MySQL手册
------第一场
START TRANSACTION;
SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
-----会话2(不再被阻止了:))
START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
更新:
认识到表中没有索引上t,我有以下的解释:
首先,事务T1将行1锁定在SELECT * FROM test WHERE t=1 FOR UPDATE
接下来,事务T2尝试执行UPDATE test SET NAME='irfandd' WHERE t=4。为了找出受影响的行,它需要扫描所有行,包括第1行。但这已被锁定,因此T2必须等待T1完成。如果存在任何类型的索引,则WHERE t=4可以使用索引来确定第1行是否包含索引t=4,因此无需等待。
选项1:添加索引,test.t以便您的更新可以使用它。
选项2: use LOCK IN SHARE MODE,仅用于放置读锁。不幸的是,此选项会导致死锁。有趣的是,T2事务执行(更新第4行),而T1失败(更新第2行)。似乎T1 也锁定了行4,并且由于T2对其进行了修改,所以T1由于事务隔离级别(默认为REPEATABLE READ)而失败。最终的解决方案是使用或事务级别来处理“事务隔离级别”。READ UNCOMMITTEDREAD COMMITTED
最简单的是选项1,恕我直言,但这取决于您的选择。
| 归档时间: |
|
| 查看次数: |
7515 次 |
| 最近记录: |