【问题标题】:PostgreSQL - how to create critical section in functionPostgreSQL - 如何在函数中创建临界区
【发布时间】:2016-09-04 09:37:20
【问题描述】:

我需要为一个用户锁定行以防止其他用户更改内容。

User A: call function lock_row() to lock row X
User B: call function lock_row() to lock row X (lock cant be created and "exception" should be triggered as row X is already locked)

不可能有用户 A 和 B 使用同一个会话连接的情况。

那么如何确保不会发生类似的事情:

User A: check if lock == 0
User B: check if lock == 0
User A: lock == 0 so SET lock = 1
User B: lock == 0 is also here so SET lock = 1

我想不通过触发器直接在 SQL 语句上创建锁(在行上更新),而是通过函数来​​允许用户在出现意外错误时释放锁。

如何创建“临界区”?如何确保函数中的关键部分正确执行?

PostgreSQL 版本 9.x.

【问题讨论】:

标签: database postgresql concurrency locking


【解决方案1】:

您所需要的只是同一事务中的独家row lock
添加NOWAIT,使事务在无法获取锁(被其他事务锁定)时立即失败。

BEGIN;

SELECT 1
FROM   tbl
WHERE  tbl_id = x
FOR    UPDATE NOWAIT;

- do something

COMMIT; -- lock released automatically

根据您的计划,限制较少的FOR NO KEY UPDATE 可能就足够了。

相关:

您可以选择将SELECT 或完整的事务包装到一个函数中。一样的效果。异常总是会跳过整个事务(除非您捕获错误)。

咨询锁是另一种选择,但不太可靠。如果您可以使用行级锁实现相同的效果,则无需回退到这个通用工具。

【讨论】:

  • 我可以在hibernate 5中使用它吗? (或者只是创建我自己宁愿避免的 SQL 语句)
  • @BartekSzczypien:我是 Postgres 的专家。不确定 Hibernate。
猜你喜欢
  • 2011-06-26
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 1970-01-01
相关资源
最近更新 更多