我试图找出系统锁定中的一些问题,并设置了以下测试,这给了我奇怪的结果。
起初它起作用了。然后,为了避免发生错误时重新运行测试,我将数据库截断从测试结束复制到测试开始,以清除状态开始。
我知道截断和咨询锁可能会死锁,但是最后一个截断应该在请求第一个咨询锁之前完成。
下面是代码和输出。如果按原样运行,它将在释放第一个锁后挂起。如果我在cleanDb
块中删除了before
,那么代码就很好了。
如果打开顺序记录,则可以看到在我开始创建测试记录之前最后一个截断已完成。
(我为什么在乎?好吧,我正在尝试使用咨询锁调试更大的问题,因此了解这一点可能有助于我理解这一点)
const models = require('../models')();
const factory = require('./factory')();
const LOCK_CODE = 2;
describe('advisory lock', function testLock() {
this.timeout(5000);
let organisation;
let person;
function delay(t, v) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, v), t)
});
}
before(async () => {
// Comment these 2 lines and everything works!?!
await cleanDb();
await delay(2000);
organisation = await factory.create('organisation');
person = await factory.create('person');
});
after(() => cleanDb());
describe.only('in session', () => {
it('does not block', () => {
const promises = [];
for (let i = 0; i < 3; i++) {
promises.push(sessionLock(organisation, person, i));
}
return Promise.all(promises);
});
});
});
async function sessionLock(organisation, person, id) {
console.log(`${id} starting`);
await models.Organisation.sequelize.query(`SELECT pg_advisory_lock(${LOCK_CODE}) FROM organisations WHERE id = ${organisation.id}`);
console.log(`${id} got lock`);
await models.Person.findAll({ where: { id: person.id } });
await models.Organisation.sequelize.query(`SELECT pg_advisory_unlock(${LOCK_CODE}) FROM organisations WHERE id = ${organisation.id}`);
console.log(`${id} finished`);
}