如何故意锁定MySQL行,即使SELECT也会返回错误?

时间:2010-01-12 18:10:28

标签: mysql locking innodb

我正在尝试使用MySQL行锁定来基本上模拟一行上的MuteEx。假设我的表有2列,一个id和一个文本字段,以及三个条目(1,a)(2,b)和(3,c)。 SELECT * FROM table;会返回这些结果。 我可以正常方式锁定特定行。

START TRANSACTION;
BEGIN;
SELECT * FROM table WHERE id = '2' FOR UPDATE;

但是,如果从第二个连接我到表中的SELECT *。它将返回所有3个结果。行级锁定是否有办法基本上阻止任何SELECT查看/使用被锁定的行?基本上我试图阻止任何人使用当前正在使用/操作的行,或甚至将行视为其数据(因为它被使用/操作)在SELECT时不可信任

4 个答案:

答案 0 :(得分:5)

如果您将事务隔离级别设置为SERIALIZABLE,则InnoDB会将LOCK IN SHARE MODE附加到所有SELECT语句中。

此模式与SELECT FOR UPDATE放置的锁相冲突,SELECT将锁定。

但请注意,InnoDB可能锁定的行数多于满足WHERE条件的行数。这是因为它锁定了扫描的所有行,而不仅仅是匹配的

说,您在col1和此查询上有一个索引:

SELECT  *
FROM    mytable
WHERE   col1 = 1
        AND col2 = 2
FOR UPDATE

使用此索引。

这将使用col1 = 1锁定所有记录,即使是那些col2 <> 2

的记录

答案 1 :(得分:5)

您需要LOCK IN SHARE MODE。与SELECT一起使用可确保没有其他人使用FOR UPDATE锁定任何行。

e.g。

客户A执行SELECT * FROM table WHERE type=2 FOR UPDATE

客户B执行SELECT * FROM table LOCK IN SHARE MODE并挂起

客户端A写入/ INSERTs / UPDATE然后执行COMMIT

客户端B现在取消冻结并恢复处理

答案 2 :(得分:2)

实际上,即使在您操作行数据 时也可以信任

如果您从一个连接启动事务,则在您提交事务之前,其他连接将不会看到您的任何更改。

答案 3 :(得分:0)

我不知道是否有一个原生的锁定特定机制来做到这一点,但我的第一个指令是给表一个状态列(例如locked)并将其设置为{{1}锁定行时。对此1敏感的用户总是会在任何查询中添加select条件。

另一方面,我不知道你在做什么,但这不是一个应该在数据库引擎之上做一两级的任务吗?