我想在基于数据库的应用程序中实现故障安全持久同步(在我的例子中是 Oracle,但希望看到 ANSI SQL 解决方案)。
我处理可以在不同线程、应用程序或服务器中运行的任务。
每种类型的任务(我区分它们ID
)可能不会同时运行——这就是我需要同步的原因。所有人都可以访问数据库,因此这是同步的好地方!
ID
每个线程/应用程序/服务器都可能失败,所以我需要一种方法来在超时后删除获取的锁。
首先想到的是使用表:
ID
STATE
TS
字段。我需要的只是原子操作:
- 尝试将
STATE
值从已完成更改为正在执行(同步)并设置TS
为当前时间。STATE
如果未完成则返回 false 。 - 尝试将
STATE
值从执行/恢复更改为恢复ifsysdate - TS > delay
并设置TS
为当前时间(以防故障)。否则返回假。
SQL更新语句主要是我想要的:
update TASK set STATE = 'executing', TS = sysdate
where ID = :id and STATE = 'completed'
和:
update TASK set STATE = 'recovering', TS = sysdate
where ID = :id and STATE in ('executing', 'recovering')
and sysdate - TS > :delay
我只看到一个问题 - 如何知道(通过 JDBC 从 Java 应用程序)是否实际执行了更新(为了成为真正的比较和交换操作)?可能是通过获取更新的行号(此信息是否可通过 JDBC 获得)?
我的假设是否正确,即更新对于where条件是原子的?
是否有另一种方法可以在基于数据库的应用程序中实现故障安全持久同步?
PS我的问题不同于:
- 在数据库中进行原子比较和交换(它有 2 个选择和更新语句,我以一个结束)。