【发布时间】:2016-07-11 05:26:24
【问题描述】:
我正在寻找一种在 Berkeley DB 中实现比较和交换操作的有效方法。现在我使用的是非常旧的版本,但乍一看,即使是最新的版本(从 Oracle 网站分发)也没有单一的方法来进行这种操作。
我正在寻找某种方法,例如
replace(Transaction, Key, ExpectedValue, NewValue)
具有以下语义:DB 获取与给定键关联的值,如果该值存在且等于 ExpectedValue,则该值将更改为 NewValue,否则方法返回不成功的 OperationStatus。
看起来没有这样的方法,所以我想知道这应该如何以最有效的方式完成。
现在我正在使用以下方法:我愿意
db.get(null, key) -> {currentValue, version}
db.put(null, key, {currentValue, newRandomIdVersion})
db.get(null, key)
我比较值和版本,如果它们匹配,我会进行最终更新擦除旧版本。如果任何步骤失败,则整个过程重新开始。
我觉得这很不理想——我错了吗?
【问题讨论】:
-
你有没有尝试过?
-
作为第一次破解,尝试使用事务,看看性能是否足够大规模。
-
你的意思是仅仅更新交易中的计数器?这无济于事 - 并发事务只会覆盖自己。
-
好吧,我不确定你所说的覆盖是什么意思——但它们会提供原子性。在发生冲突时,一个事务胜负 N 个事务,由您的应用程序重试。如果您确实需要对同一“记录”进行并发写入,请查看是否可以弄清楚如何将其拆分为多个记录。有了这里的内容,您最好使用环形日志,并在恢复时整理出正确的应用程序级状态。
-
是的,你是对的,事务是原子的,但同样,如果它们同时开始更新同一个记录,第一个事务可能不会“看到”第二个事务更新记录的结果,反之亦然。同时比较和交换假定不会丢失任何更新。
标签: java concurrency berkeley-db berkeley-db-je