我正在使用c3p0和postgres。我有一个多线程应用程序,在没有正确锁定的情况下,不同的线程可能会意外更新同一条记录。为了防止这种情况,我打算使用咨询锁。
SELECT pg_advisory_lock(id) FROM ...;
但是,我不确定我是否可以将建议锁与连接池结合使用,因为用于创建锁的连接会被关闭(这对应用程序逻辑是透明的)?相应的锁是否被释放?
答案 0 :(得分:6)
是,在关闭连接时会释放锁定(建议和其他方式)。
但是,如果将连接返回到池,则它们可能不必须被释放;事务级锁定将由于pooler将ROLLBACK
任何打开的事务,但只有在连接池将会话返回到连接池后,如果您的连接池知道run the PostgreSQL-specific DISCARD ALL;
statement,则咨询锁才会被释放。
为了防止这种情况,我打算使用咨询锁。
为什么呢?您正在阻止对记录的更新,因此您可以使用普通行来锁定。您的流程应该是:
SELECT * FROM the_table WHERE id = 123 FOR UPDATE
UPDATE the_table SET whatever = blah WHERE id = 123
这要求您在同一连接上执行 open transaction 以执行这三个步骤。如果您的体系结构阻止您这样做并在(2)之后将连接返回到池,那么它可能也会阻止使用建议锁定,因为您需要持有相同的底层连接来管理建议锁定。
如果是这种情况,您必须使用optimistic concurrency control(通常称为"乐观锁定"),这是为无状态Web应用程序创建的设计。您在实体中存储版本字段,您的流程类似于:
SELECT col1, col2, entity_version FROM the_table WHERE id = 123
(假装entity_version
返回值42
)UPDATE the_table SET whatever = blah, entity_version = 43 WHERE id = 123 AND entity_version = 42
如果entity_version
已被其他会话更改,则WHERE
上的UPDATE
子句不匹配,更新将影响零行。您可以测试受影响的行数并重试整个操作,或在发生这种情况时向用户报告错误。
乐观并发控制由许多ORM实现,如Hibernate和其他JPA ORM。您不必将其与ORM一起使用,这只是最常见的用途,因为ORM鼓励"选择然后更新"反模式,否则SQL DB需要避免这种情况。