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