确保使用JDBC对数据库表进行原子读取的最佳实践是什么?

Dav*_*hao 14 database jdbc

我有一个java应用程序从数据库表读取要处理的作业,我可能有多个这个应用程序的实例在不同的服务器上运行,因为每个作业是独立的.一旦找到作业进行处理,其状态将更新为"正在运行".我想要确保从每个实例检索要处理的作业是原子的,我如何使用JDBC实现这一点?

Gor*_*son 5

一种完全通用*但可能效率稍低的方法是使用服务器特定的标识符来"声明"作业,方法是首先将其状态更新为该标识符,然后根据该值检索作业.例如,如果您在同一网络上使用Windows服务器,那么它们的服务器名称将唯一标识它们.如果你的表看起来像

JobID  JobName  Status
-----  -------  ---------
    1  Job_A    Completed
    2  Job_B
    3  Job_C
Run Code Online (Sandbox Code Playgroud)

如果无人认领的作业具有状态,NULL则在SERVER1上运行的应用程序可以通过执行setAutoCommit(true)后续操作来声明作业

UPDATE Jobs SET Status='SERVER1'
WHERE JobID IN (
    SELECT TOP 1 JobID FROM Jobs 
    WHERE Status IS NULL
    ORDER BY JobID)
Run Code Online (Sandbox Code Playgroud)

如果ExecuteUpdate返回0则没有待处理的作业.如果它返回1,那么你可以得到行

SELECT JobID, ... FROM Jobs WHERE Status='SERVER1'
Run Code Online (Sandbox Code Playgroud)

然后使用参数化查询将其状态更新为"正在运行"

UPDATE Jobs SET Status='Running' WHERE JobID=?
Run Code Online (Sandbox Code Playgroud)

在哪里提供从上一个SELECT中检索到的JobID.

*(即,不依赖于任何特定的SQL扩展,显式锁定或事务处理)


Wil*_*ung 2

使用数据库服务器支持的任何机制锁定表。

例如,在 Postgres 中它将是:

LOCK yourtable;
Run Code Online (Sandbox Code Playgroud)

这是您在交易期间的表格。

其他数据库也会有类似的东西。