微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Postgres 中带有嵌套 SELECT 子句的原子更新

如何解决Postgres 中带有嵌套 SELECT 子句的原子更新

我有一个集群,其中一个节点是主节点。通过数据库(通过java/spring/jpa访问Postgres)完成同步/决定谁将成为新的master。

这是我目前拥有的

@Repository
public interface ServiceRepository{


@Transactional
@Modifying
@Query("UPDATE ServiceInstance e SET e.master=true"
        + " where e.id=:serviceId AND NOT"
        + " EXISTS (SELECT master from ServiceInstance where master = true)")
int tryToBecomeMaster(@Param("serviceId") String serviceId);

对于集群中的每个节点,DB 中都有一行 ServiceInstance。每个节点都试图更新自己的行,但前提是没有行已标记为“主”。该查询由每个节点定期运行。

查询原子还是存在竞争条件?如果它不是原子的,我在这里需要什么事务隔离级别?

我主要担心的是,如果允许并行执行 2 个查询,它们可能会将 SELECT 子句计算为 false(无主)并更新它们的行。

解决方法

为了确保只能有一个 master,在表上创建一个唯一的部分索引:

CREATE UNIQUE INDEX ON serviceinstance ((1)) WHERE master;

一旦您尝试将表中多于一行的 master 设置为 TRUE,这将给您一个错误,并且 ACID 保证(一致性)的 C 将确保这总是有效的。您必须在函数中捕获并处理异常。

我要指出,这不是实现高可用性集群的好方法:它具有数据库形式的单点故障。

,

如果你想确保你的 SELECT 子句不能被并行读取,你可以使用带有聚合函数的 SELECT FOR UPDATE 来检测 master 而不是 WHERE 子句;这将自动锁定表的所有行,直到 UPDATE 完成。

另一种方法是手动执行 LOCK TABLE EXCLUSIVE 命令。

两者都应该在您的情况下正常工作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?