Postgresql 为什么在与pg promise进行交易时不能解锁建议锁?

Postgresql 为什么在与pg promise进行交易时不能解锁建议锁?,postgresql,postgresql-9.5,pg-promise,Postgresql,Postgresql 9.5,Pg Promise,我遇到了以下代码并试图对其进行调试,但我不明白为什么在这种情况下无法解锁锁: 常数db=pgpopts wait db.one'SELECT pg\u try\u advisional\u lock1 AS lock'//返回true,我可以在db中看到锁 //无需等待 db.txasync t=>{ const fingerprintIds=fingerprints.mapitem=>item.id sql=`UPDATE fingerprint SET blah=1,其中$fingerpri

我遇到了以下代码并试图对其进行调试,但我不明白为什么在这种情况下无法解锁锁:

常数db=pgpopts wait db.one'SELECT pg\u try\u advisional\u lock1 AS lock'//返回true,我可以在db中看到锁 //无需等待 db.txasync t=>{ const fingerprintIds=fingerprints.mapitem=>item.id sql=`UPDATE fingerprint SET blah=1,其中$fingerprintIds中的id:列表返回id` const updatedFingerprintIds=await db.querysql,{fingerprintIds}//是,它没有使用事务对象 //其他一些数据库调用 } 结果=等待数据库。一个“选择pg_advisory_unlock1作为锁” //result.lock===false,数据库记录错误:“警告:您没有ExclusiveLock类型的锁” //锁仍然保留在数据库中,直到会话结束 当然,当我在db.tx调用前面添加wait,并在事务回调中使用t时,它会按预期工作

发生这种情况是因为调用解锁时pg promise库处于事务状态吗?因为当我调用这一系列查询时,锁将按预期解锁:

SELECT pg_try_advisory_lock(1) AS lock;
BEGIN;
SELECT * FROM table;
SELECT pg_advisory_unlock(1) AS lock;

这些锁定操作是当前连接会话独有的,因此必须在同一事务块中执行:

等待db.txasync t=>{ 等待t.func的“pg_try_advision_lock”[1]; //根据“t”上下文在此处执行所有查询; // ... 等待t.func的“pg_咨询_解锁”[1]; }; 我们在这里使用方法只是为了缩短语法。 但是,如果事务失败,它将不会执行解锁,因此如果这是一个问题,那么您需要手动捕获事务中的错误:

等待db.txasync t=>{ 等待t.func的“pg_try_advision_lock”[1]; 让结果,犯错; 试一试{ //根据“t”上下文在此处执行所有查询; //并设置“结果”。。。 }抓住{ err=e; } 等待t.func的“pg_咨询_解锁”[1]; 生命体{ 投掷e; } 返回结果; }; 更新


我之所以使用咨询锁,是因为在这一个数据库事务之外还有很多其他非幂等、非数据库的事情发生,而且因为有多个应用程序实例正在运行,所以锁是为了防止其他实例同时执行相同的工作

我不确定这种类型的锁如何在多个数据库甚至多个应用程序中发挥作用,因为这些锁只能在同一个会话中工作

但是,如果您确实需要在事务之外执行这些锁,并且针对相同的连接,那么您需要手动管理连接:

//在你的逻辑链条的开始处, //您可以分配手动管理的连接: const dbm=等待db.connect; //然后锁定发生: 等待dbm.func'pg_try_advision_lock',[1]; //然后你的交易发生了。。。 等待dbm.txasync t=>{ //事务查询 }; //然后,您的解锁查询: 等待dbm.func'pg_advision_unlock',[1]; //然后释放连接: dbm.done; 你只需要小心,不要泄漏连接

见方法。
我不知道pg承诺,但会话级别的咨询锁独立于事务。如何以及何时使用任务和事务。你为什么不遵循这个模式呢?上面的代码很糟糕,因为您创建了一个事务上下文,但实际上并没有使用它。是的,我意识到:这不是我的代码,但我试图理解其行为。该示例有点做作,我不能只是在事务块中插入锁,因为锁定和解锁的调用在调用堆栈中的位置更高。我只是想理解为什么在开始执行事务时锁无法解锁,但我可以在原始状态下解锁sql@BrDaHa在开始之前执行锁有什么好处吗?我使用的是建议锁,因为还有很多其他东西是非幂等的,在这一数据库事务之外发生的非数据库事务,并且由于有多个应用程序实例正在运行,因此锁定是为了防止其他实例在同一时间执行相同的工作time@BrDaHa我不明白。您使用的锁是特定于会话的,这意味着它只能针对当前连接工作。它不能跨多个数据库实例或多个应用程序使用。单个数据库,多个应用程序。如果其他应用程序未首先获得锁,Try advisory lock会在不同会话中返回false。