c3p0:会话级咨询锁

时间:2013-07-24 07:20:42

标签: postgresql c3p0

我正在使用c3p0和postgres。我有一个多线程应用程序,在没有正确锁定的情况下,不同的线程可能会意外更新同一条记录。为了防止这种情况,我打算使用咨询锁。

SELECT pg_advisory_lock(id) FROM ...;

但是,我不确定我是否可以将建议锁与连接池结合使用,因为用于创建锁的连接会被关闭(这对应用程序逻辑是透明的)?相应的锁是否被释放?

1 个答案:

答案 0 :(得分:6)

是,在关闭连接时会释放锁定(建议和其他方式)。

但是,如果将连接返回到池,则它们可能必须被释放;事务级锁定将由于pooler将ROLLBACK任何打开的事务,但只有在连接池将会话返回到连接池后,如果您的连接池知道run the PostgreSQL-specific DISCARD ALL; statement,则咨询锁才会被释放。

  

为了防止这种情况,我打算使用咨询锁。

为什么呢?您正在阻止对记录的更新,因此您可以使用普通行来锁定。您的流程应该是:

  1. 检查连接池中的连接
  2. SELECT * FROM the_table WHERE id = 123 FOR UPDATE
  3. 完成应用程序中所需的工作
  4. UPDATE the_table SET whatever = blah WHERE id = 123
  5. 将连接返回到连接池
  6. 这要求您在同一连接上执行 open transaction 以执行这三个步骤。如果您的体系结构阻止您这样做并在(2)之后将连接返回到池,那么它可能也会阻止使用建议锁定,因为您需要持有相同的底层连接来管理建议锁定。

    如果是这种情况,您必须使用optimistic concurrency control(通常称为"乐观锁定"),这是为无状态Web应用程序创建的设计。您在实体中存储版本字段,您的流程类似于:

    1. SELECT col1, col2, entity_version FROM the_table WHERE id = 123(假装entity_version返回值42
    2. 完成应用中所需的工作
    3. UPDATE the_table SET whatever = blah, entity_version = 43 WHERE id = 123 AND entity_version = 42
    4. 如果entity_version已被其他会话更改,则WHERE上的UPDATE子句不匹配,更新将影响零行。您可以测试受影响的行数并重试整个操作,或在发生这种情况时向用户报告错误。

      乐观并发控制由许多ORM实现,如Hibernate和其他JPA ORM。您不必将其与ORM一起使用,这只是最常见的用途,因为ORM鼓励"选择然后更新"反模式,否则SQL DB需要避免这种情况。