java - 使用 java lock 或 catch 数据库异常
问题描述
每次有新数据进来,我都会检查数据库,如果有与新数据相关的记录,我会得到它并根据新数据和旧记录更新记录;如果不存在记录,我将为新数据创建一个新记录;
问题:当有多个线程做同样的事情时,它自然会形成一个read -> check -> update
模式,导致竞争条件。
我尝试了以下解决方案,但它们似乎都不太好。
为 db 添加唯一约束
aFieldOrSeveralFields
,尝试捕获SQLIntegrityConstraintViolationException
然后重试该read -> check -> update
过程;- 我可以抓住
Exception
,但对我来说看起来很危险; - 或者我可以检查一下
e instanceof SQLIntegrityConstraintViolationException
,让其他异常冒出来,但看起来很难看;
- 我可以抓住
synchronised
整体使用read -> check -> update
但似乎相当无效,因为有明显的I/O操作。
更新于 2019-03-11
最后,为了平衡丑陋的处理和有效性,我将任务拆分为更小的任务,synchronised
以确保数据的一致性,并且到目前为止没有出现明显的性能问题。
解决方案
我认为你在做正确的事,但我不明白为什么这里会抛出异常?(也许你可以澄清一下)。
在我看来,正确的流程是这样的:
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,在此处阅读更多信息,
推荐阅读
- pyside2 - pycairo + PySide2 小部件?
- python - 使用 Tkinter 对话框从多个 .csv 文件在一个图形中创建多个图
- node.js - Cassandra 是无模式的吗?
- c# - 如何在客户端(blazor webassembly)调用创建 webapi(blazor 服务器应用程序)
- printing - 控制台/命令窗口上的输出始终为字符串形式/类型?
- c# - 如何在 EF Core 3 中动态获取 DbSet?
- batch-file - 写入 VBS 文件的批处理作业
- android - 防止活动出现多次
- c# - InvalidOperationException:尝试激活“TaskAPI”时无法解析“ITasksLogicClass”类型的服务
- r - 是否有基于缺失年份添加行的 R 函数?