Java 如何防止这两个应用程序同时更改共享数据?即使我已经使用了“选择更新”?
我有两个带有共享数据库的应用程序。实际上,这两个应用程序正试图每x秒更新一行。该表如下所示:Java 如何防止这两个应用程序同时更改共享数据?即使我已经使用了“选择更新”?,java,postgresql,Java,Postgresql,我有两个带有共享数据库的应用程序。实际上,这两个应用程序正试图每x秒更新一行。该表如下所示: | host_name | acquired | attribute | | --------- | -------- | ---------- | | app1 | TRUE | 'xyz' | 在上表中,属性必须是唯一的。主机名可能会根据获取它的应用程序的不同而变化。因此,如果app2具有获取的属性,它将保持该属性x秒,然后将获取的设置为false,app2和app
| host_name | acquired | attribute |
| --------- | -------- | ---------- |
| app1 | TRUE | 'xyz' |
在上表中,属性必须是唯一的。主机名可能会根据获取它的应用程序的不同而变化。因此,如果app2具有获取的属性,它将保持该属性x秒,然后将获取的设置为false,app2和app1将竞相获取该属性,以再次获取特定属性
为此,我使用了postgres的select For update语句,因此如果app2获取了该属性,它将锁定该行,而app1在释放该锁定之前无法更改该行。我最初认为,选择更新是防弹的,但我错了。几天前,锁坏了。我假设app1和app2同时获得锁。我想知道我是否可以加强这一点,这样下次就不会发生了。有什么建议吗?在您的update语句中,尝试类似这样的更改主键ID的方法,希望主键是integer或bigint
select * from my_table
where attribute='xyz'
and pg_try_advisory_lock(id)
for update
别忘了跑步
pg_advisory_unlock()
当你处理完这一行后。没有什么是防弹的。这只是软件。你可以尝试一种更乐观的方法。 将“更新计数器”行添加到表中。 在更新行之前,您读取该行以获取当前计数器值,并在update语句中添加where条件以确保仅在其他进程未更改计数器时更新该行 执行后,检查行是否已更改。如果是,一切都好。如果没有,请在出现故障时执行任何操作。app1和app2同时获得锁-这是不可能的。Postgres事实上没有一个DBMS允许两个不同的事务在同一行上获取锁。
Update my_table set x=y, counter=counter+1 where counter=read_before