如何在不等待MySQL的情况下返回物理锁定错误

时间:2012-05-12 08:01:57

标签: java mysql locking sql-update ibatis

在我的项目中使用java,ibatic和MySql。

在将数据更新到数据库之前,我使用 SELECT FOR UPDATE查询

锁定表
eg: SELECT * FROM MEM_MST WHERE MEM_ID = #memId# FOR UPDATE

它可以正确锁定桌子。但问题是,例如,如果两个客户端同时更新表。第一个是锁定表并更新,但第二个正在等待更新,直到锁被释放。之后第二个也更新数据。因此,首先更新一个更新的数据。请参阅以下说明:

Time |  Client 1           | Client 2  
-------------------------------------------------
1    | SELECT FOR UPDATE   | 
2    | UPDATE              | SELECT FOR UPDATE (Waiting) 
3    | COMMIT              | (Waiting)
4    |                     | UPDATE
5    | (Overwritten)       | COMMIT

因此,客户端1更新的数据丢失

我想要的只是简单地将错误消息返回给客户端2而不是等到锁定被释放。

请告诉我解决上述问题的方法。


P.S:

我已经在启动变量中将锁定等待超时设置为0,但是仍然需要大约2秒才能告诉“超出锁定等待超时”消息。

此外,SELECT FOR UPDATE NO WAIT在MySQL中不起作用

1 个答案:

答案 0 :(得分:0)

不幸的是,innodb_lock_wait_timeout不能设置为低于1.

您必须实现自己的同步机制。作为eggyal建议的替代方案,您可以在关键表中添加“信号量”字段。基本工作流程(伪代码):

START TRANSACTION;
SELECT locked FROM MEM_MST WHERE MEM_ID = @id FOR UPDATE;
if (previous_result == 1) {
    ROLLBACK;
    throw new Exception();
}
UPDATE MEM_MST SET locked = 1 WHERE MEM_ID = @id;
COMMIT; -- from now on, concurrent attempts will fail immediately

START TRANSACTION;
UPDATE MEM_MST SET whatever = @some_value WHERE MEM_ID = @id;
UPDATE MEM_MST SET locked = 0 WHERE MEM_ID = @id; -- release lock
COMMIT;