我遇到了以下代码,并试图对其进行调试,但我不明白为什么在这种情况下无法将锁解锁:
const db = pgp(opts)
await db.one('SELECT pg_try_advisory_lock(1) AS lock') // returns true, and I can see the lock in the DB
// no await
db.tx(async t => {
const fingerprintIds = fingerprints.map(item => item.id)
sql = `UPDATE fingerprint SET blah=1 WHERE id IN ($(fingerprintIds:list)) RETURNING id`
const updatedFingerprintIds = await db.query(sql, { fingerprintIds }) // yes, it is not using the transaction object
// some other database calls
})
result = await db.one('SELECT pg_advisory_unlock(1) AS lock')
// result.lock === false, database logs the error: 'WARNING: you don't own a lock of type ExclusiveLock'
// lock still stays in the database (until the session ends)
当然,当我在await
调用之前添加db.tx
,并在事务回调中使用t
时,它会按预期工作。
发生这种情况是因为在调用unlock
时pg-promise库处于事务状态吗?因为当我调用这一系列查询时,锁将按预期方式解锁:
SELECT pg_try_advisory_lock(1) AS lock;
BEGIN;
SELECT * FROM table;
SELECT pg_advisory_unlock(1) AS lock;
这些锁定操作是当前连接会话所独有的,因此必须在同一连接会话内执行:
await db.tx(async t => {
await t.one('SELECT pg_try_advisory_lock(1) AS lock');
// execute all queries here, against 't' context;
// ...
await t.one('SELECT pg_advisory_unlock(1) AS lock');
});