请对以下问题提供一些建议: 我有一个唯一代码列表。代码必须只使用一次,因此每个代码都有一个状态(使用/未使用)。
如果多个线程试图获取下一个未使用的代码,我担心争用/竞争条件。
使用SQL数据库(在我的情况下是MySQL)实现它的最佳方法是什么?
第一个选项是使用锁定和读取提交的隔离级别:
start transaction in read-committed isolation level
select code from code_table where status = 'not-used' for update
update code_table set status = 'used' where code = :code
commit transaction
在争用线程的情况下,我认为“数据库线程”会在锁定的行上偶然发现,除非行写入锁定将被释放,否则将会看到(因为读取已提交的隔离级别)代码记录已被使用并转移到其他代码记录。
第二个选项是使用类似于hibernate乐观锁定的东西(我们不使用hibernate),这里是步骤的描述:
start transaction in default isolation level ( read-repeatable )
select code from code_table where status = 'not-used'
commit transaction
start transaction in default isolation level ( read-repeatable )
update code_table set status = 'used' where code = :code
commit transaction
在Java代码中,我将检查更新了多少记录。如果有一条记录更新,一切正常,如果有0条记录更新 - 我重复步骤...在第3(或第5)试验后 - 抛出异常。
任何帮助/建议都将受到高度赞赏。 提前谢谢
答案 0 :(得分:2)
第二种选择 - 乐观锁定 - 似乎是一个非常糟糕的主意 来自WIkipedia:https://en.wikipedia.org/wiki/Optimistic_concurrency_control
乐观并发控制(OCC)。 。 。 。 。 。 。
。 。 。 。 。 。 。 。通常用于 数据争用率低的环境。当冲突很少时, 事务可以完成,而无需管理锁和 没有交易等待其他交易'锁定 清除,导致比其他并发控制更高的吞吐量 方法。但是,如果频繁争用数据资源,那么 反复重启事务的成本会损害性能 显著强>;人们普遍认为其他并发控制 方法在这些条件下具有更好的性能。然而, 基于锁定("悲观")方法也可以提供差 性能,因为锁定可以大大限制有效 即使在避免死锁的情况下也能实现并发。
我可以很容易地想象出X并发线程的以下场景:
你必须坚持第一个选择。
为了减少争用,您可能希望将事务保持尽可能短。