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

时间:2012-05-09 02:14:01

标签: c# mysql innodb

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

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

结帐LOCK TABLESUNLOCK TABLES

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

您可以将此与Mark的答案结合使用。

答案 2 :(得分:0)

相关问题