首页 > 解决方案 > 使用 java lock 或 catch 数据库异常

问题描述

每次有新数据进来,我都会检查数据库,如果有与新数据相关的记录,我会得到它并根据新数据和旧记录更新记录;如果不存在记录,我将为新数据创建一个新记录;

问题:当有多个线程做同样的事情时,它自然会形成一个read -> check -> update模式,导致竞争条件


我尝试了以下解决方案,但它们似乎都不太好。

  1. 为 db 添加唯一约束aFieldOrSeveralFields,尝试捕获SQLIntegrityConstraintViolationException然后重试该read -> check -> update过程;

    • 我可以抓住Exception,但对我来说看起来很危险
    • 或者我可以检查一下e instanceof SQLIntegrityConstraintViolationException,让其他异常冒出来,但看起来很难看;
  2. synchronised整体使用read -> check -> update但似乎相当无效,因为有明显的I/O操作。


更新于 2019-03-11

最后,为了平衡丑陋的处理有效性,我将任务拆分为更小的任务,synchronised以确保数据的一致性,并且到目前为止没有出现明显的性能问题。

标签: javapostgresqlhibernatespring-bootrace-condition

解决方案


我认为你在做正确的事,但我不明白为什么这里会抛出异常?(也许你可以澄清一下)。

在我看来,正确的流程是这样的:

record <- readFromDB(uniqueFields)
if record does not exist:
    record <- createRecord()
updateFields(record) //here you should update the non-unique fields
saveToDB(record)     //it shouldn't throw an exception since the unique fields didn't change

另一种可能的解决方案是根据您的用例使用 ON DUPLICATE KEY UPDATE/IGNORE,在此处阅读更多信息,


推荐阅读