Mysql中的行级锁定

时间:2015-11-19 09:45:49

标签: mysql innodb rowlocking

我在表格中有5行(1到5)。我希望第2行锁定某些更新,同时如果有人试图更新第4行,那么他应该能够更新。

我正在尝试使用下面的代码,但我觉得它将锁定放在表级别而不是行级别。

------第1节

START TRANSACTION;
SELECT * FROM test WHERE t=1 FOR UPDATE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;

-----会话2(被阻止)

START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;

2 个答案:

答案 0 :(得分:4)

而不是FOR UPDATE使用LOCK IN SHARE MODEFOR UPDATE也阻止其他事务读取行。 LOCK IN SHARE MODE允许读取,但阻止更新。

参考:MySQL Manual

------第1节

START TRANSACTION;
SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
UPDATE test SET NAME='irfandd' WHERE t=2;
COMMIT;

-----会话2(不再被阻止:))

START TRANSACTION;
UPDATE test SET NAME='irfandd' WHERE t=4;
COMMIT;

<强>更新

t上意识到表没有索引,我有以下解释:

首先,事务T1锁定SELECT * FROM test WHERE t=1 FOR UPDATE

中的第1行

接下来,事务T2尝试执行UPDATE test SET NAME='irfandd' WHERE t=4。要找出受影响的行,需要扫描所有行,包括第1行。但是这是锁定的,所以T2必须等到T1结束。 如果存在任何类型的索引,WHERE t=4可以使用索引来确定第1行是否包含t=4,因此无需等待。

选项1:test.t上添加索引,以便您的更新可以使用它。

选项2:使用LOCK IN SHARE MODE,用于仅设置读锁定。 不幸的是,这个选项会造成死锁。有趣的是,T2事务执行(更新第4行),T1失败(更新第2行)。似乎T1读取锁定第4行,并且由于T2修改它,因为事务隔离级别(REPEATABLE READ by default),T1失败。使用READ UNCOMMITTEDREAD COMMITTED交易级别,最终解决方案将使用Transaction Isolation Levels

最简单的是选项1 ,恕我直言,但这取决于您的可能性。

答案 1 :(得分:0)

我发现下面的选项更合适我同时从并发会话生成40000个数字。我没找到任何重复的号码。没有下面的命令我生成10000个数字,发现5个重复的数字。

START TRANSACTION

SELECT * FROM test WHERE t = 1 FOR UPDATE;

更新测试SET NAME ='irfandd'WHERT = 2;

COMMIT;