0

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

4

3 回答 3

1

假设您只能为每个代理锁定 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...FOR UPDATE 的更新锁:

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;
于 2012-05-09T02:21:44.893 回答
0

签出LOCK TABLESUNLOCK TABLES

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

您可以将其与马克的回答结合使用。

于 2012-05-09T02:29:37.127 回答
0

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

于 2012-05-09T02:54:16.857 回答