PostgreSQL 咨询锁不适用于 Doctrine 的 DBAL
Posted
技术标签:
【中文标题】PostgreSQL 咨询锁不适用于 Doctrine 的 DBAL【英文标题】:PostgreSQL advisory locks are not working with Doctrine's DBAL 【发布时间】:2015-06-04 00:23:01 【问题描述】:我在 Doctrine 的 DBAL 中尝试使用 advisory locks 时遇到了一种非常奇怪的行为。
我有一个 Symfony 2 应用程序,我想在其中获得某个实体的咨询锁。我正在执行以下查询以获取锁:
SELECT pg_try_advisory_lock(83049, 5)
通过以下 php 代码:
/** @var Doctrine\DBAL\Connection */
protected $connection;
public function lock()
return $this->connection->fetchColumn(
"SELECT pg_try_advisory_lock($this->getTableOid(), $this->entity->getLockingId())"
);
我创建了以下脚本来测试并发性:
// Obtaining the lock.
$locker->lock();
// Doing something for ten seconds.
sleep(10);
但是,当我同时运行它时,看起来每个实例都成功获得了锁。此外,在请求终止后,看起来锁会自动释放,即使我没有调用unlock()
。
为什么会这样?
教义是否对所有请求都使用单一连接?
script 终止后是否会自动释放锁?
【问题讨论】:
【参考方案1】:13.3.4。咨询锁
PostgreSQL 提供了一种创建锁的方法,该锁具有 应用程序定义的含义。这些被称为咨询锁,因为 系统不会强制使用它们——这取决于应用程序 正确使用它们。咨询锁可用于锁定 不适合 MVCC 模型的策略。例如,一个 咨询锁的常见用途是模拟悲观锁 所谓的“平面文件”数据管理系统的典型策略。 虽然存储在表中的标志可以用于相同的目的, 咨询锁更快,避免表膨胀,并且是自动的 在会话结束时由服务器清理。
在 PostgreSQL 中有两种获取咨询锁的方法: 会话级别或事务级别。一旦在会话级别获得, 一个咨询锁被持有直到显式释放或会话 结束。与标准锁请求不同,会话级咨询锁 请求不遵守事务语义:在 稍后回滚的事务仍将在 回滚,同样解锁是有效的,即使调用 稍后交易失败。一个锁可以被多次获取 拥有过程;对于每个完成的锁定请求,必须有一个 在实际释放锁之前的相应解锁请求。 另一方面,事务级锁定请求的行为更像 常规锁请求:它们在结束时自动释放 事务,并且没有显式的解锁操作。这 行为通常比会话级别的行为更方便 建议锁的短期使用。会话级和 对同一咨询锁标识符的事务级锁请求 将以预期的方式相互阻止。如果会话已经举行 给定的咨询锁,它的附加请求将始终成功, 即使其他会话正在等待锁定;这个说法是真的 无论现有的锁定保持和新请求是否在 会话级别或事务级别。
http://www.postgresql.org/docs/9.1/static/explicit-locking.html
【讨论】:
谢谢,你是对的。我错过了automatically cleaned up by the server at the end of the session
部分。但是为什么多个客户端可以同时获得同一个锁呢?
在尝试更新锁定行时开始等待另一个事务。以上是关于PostgreSQL 咨询锁不适用于 Doctrine 的 DBAL的主要内容,如果未能解决你的问题,请参考以下文章
自动回滚不适用于 Postgresql 上的 liquibase