postgresql 的原子更新 table

Atomic Update for postgresql table

背景

我有一个简单的功能可以更新我的 table。每当我执行我的脚本 foo_script.py 时,我都会调用此函数 set_status 来创建时间戳。完成该过程后,我调用函数 remove_status 使 table NULL 中的条目。

我还有一个名为 db.py 的包装脚本,它允许我执行 sql 语句,因此在我的代码中我使用 db.execute() 但这与我这里的问题无关。

思路是foo_script.py不能运行并发

代码

def set_status() -> None:
    db.execute(
        ENVIRONMENT=db.get_environment(),
        sql="UPDATE my_table SET status_process = NOW()",
    )

def remove_status() -> None:
    db.execute(
        ENVIRONMENT=db.get_environment(),
        sql="UPDATE my_table SET status_process = NULL",
    )

问题

不幸的是,脚本 foo_script.py 可能会被 2 或更多意外地 运行。我想避免任何竞争条件。我如何确保我所做的查询是原子的。我是 sql 的新手,我不确定如何实现。

这听起来像是 advisory locks 的典型应用。

如果使用它们,则不需要锁定数据库中的对象来同步操作。此外,咨询锁可以独立于事务,因此您不必拥有长时间的数据库事务及其所有相关的不愉快。

要抢锁,运行

SELECT pg_advisory_lock (42);

并释放它,运行

SELECT pg_advisory_unlock(42);

42为锁号;你当然可以自由选择不同的。