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为锁号;你当然可以自由选择不同的。
背景
我有一个简单的功能可以更新我的 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为锁号;你当然可以自由选择不同的。