在我的项目中使用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,而不是等到解锁。
请告诉我解决上述问题的方法。
附言:
我已经在启动变量中将锁定等待超时设置为 0,但仍然需要大约 2 秒才能告诉"超出锁定等待超时"消息。
此外,SELECT FOR UPDATE NO WAIT
在MySQL中不起作用
不幸的是,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;