如何防止其他会话在更新发生之前选择一行

本文关键字:选择 一行 其他 何防止 会话 更新 | 更新日期: 2023-09-27 18:33:45

我正在用C#编写一个呼叫中心程序,其中多个座席从表中逐个加载客户。为了防止多个代理加载同一客户,我在表中添加了一个新字段以显示该行已锁定。选择一行时,我会更新该行并将锁定字段设置为选择该行的代理的 ID。但是问题是在我选择该行并锁定它期间,另一个代理可以选择同一行,因为它尚未锁定!有没有办法处理这种情况?数据库是MySQL 5/InnoDB

如何防止其他会话在更新发生之前选择一行

假设每个代理只能锁定 1 个配置文件:

--Check for no lock
UPDATE T SET LockField = 'abc' WHERE ProfileId = 1 AND LockField IS NULL;
--Check to see if we updated anything. 
--If not, we can't show this row because someone else has it locked
SELECT ROW_COUNT();

在执行更新之前,我必须选择id...

如果在 1 语句中执行 UPDATE 操作,则不会。我们对MySQL语法的了解有点超出 - 但像这样:

--Check for no lock
UPDATE T SET LockField = 'abc' WHERE ProfileId = (
   SELECT ProfileId FROM T WHERE LockField IS NULL LIMIT 1
);
--Check to see what we updated
SELECT * FROM T WHERE LockField = 'abc';

工作很容易。

如果你想变得更复杂一点(或者MySQL不支持子查询),你可以使用带有SELECT的更新锁...更新:

START TRANSACTION;
--Put an update lock on the row till the xaction ends
--any other SELECT wanting an update lock will block until we're out of the xaction
SELECT @id = ID FROM T WHERE LockField IS NULL LIMIT 1 FOR UPDATE;
UPDATE T SET LockField = 'abc' WHERE ID = @id;
COMMIT TRANSACTION;

查看LOCK TABLESUNLOCK TABLES

http://dev.mysql.com/doc/refman/5.6/en/lock-tables.html

你可以把它与马克的答案结合使用。

您描述的是乐观并发与悲观并发。