我有一个 Java 前端和一个 MySQL 后端方案,我对 SELECT 使用了“锁定共享模式”。如果我从另一个进程请求同一行,它会提供数据。但是它不允许我更新。我想做的是通知用户他们只会有一个只读副本,所以如果他们希望看到他们可以看到的信息,他们可以稍后再请求。我如何检查 ROW 的状态以便用户会被告知这种情况??如果我使用“FOR UPDATE”,它只会等到第一个用户保存数据。我发现它对用户不太友好,如果他们只有一个空白屏幕或者当他们单击按钮时它什么也不做。任何帮助将不胜感激。使用 MySQL 5.5、Java 7。
2 回答
简短的回答是“你不能”!
您可能想看看这个讨论。
[编辑]
该帖子的答案指出:
对于未命名的锁,您不能(检查锁的状态)!!!!更多信息: http: //forums.mysql.com/read.php?21,222363,223774#msg-223774
行级锁不适用于应用程序级锁。它们只是实现一致读写的手段。这意味着您必须尽快释放它们。您需要实现自己的应用程序级锁,这并不难。也许一个简单的user_id
领域就可以了。如果它为空,则没有锁。但如果它不为空,则 id 表示谁持有该记录。在这种情况下,您需要行级锁定来更新user_id
字段。正如我之前所说,一旦你完成锁定/解锁记录,你就必须释放 MySQL 锁。
这个问题的全部前提在于直接将 RDBMS 的行级锁定(通常用于短期并发控制)相当自由地用于交互式 UI 控制。
但抛开这一点并回答问题,可以将会话设置innodb_lock_wait_timeout
为一个非常短的值,最小值为1
,并捕获超出的锁定等待超时;无法锁定时尝试重新启动事务。
异常类是com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException
我刚尝试使用的时候mysql-connector-java 5.1.38
,但其他异常类在版本中发生了变化,所以这在旧版本的 MySQL Connector/J 中也可能不同。
获取锁的“尝试和失败”方法是处理这些类型的并发情况的标准方法,因为“尝试前检查”的替代方法是一种反模式,它在检查和实际尝试之间创建竞争条件锁。