您好,我正在尝试创建一个队列,以便在有人点击正在使用 sequelize.js 在我的 postgres 数据库上进行更新的 api 路由时。我的主要目标是防止对一行数据进行并发修改。
addFile(req, res) {
// repoPath = directory being watched
// localPath = full local path change was made on
const { repoPath, localPath, data, className, lessonName, lessonId, classCode } = req.body;
const { pathToRepoStorage, subPath, fileDirectory } = this.pathMaker(repoPath, localPath, className, lessonName);
let repo = null;
return sequelize.transaction((t) => {
// chain all your queries here. make sure you return them.
return Lesson.findById(lessonId,
{
transaction: t,
})
.then((lesson) => {
repo = lesson.get('repo');
this.addNodeToTree(repo, fileDirectory, subPath);
return Lesson.update({ repo },
{
where: {
id: lessonId,
},
transaction: t,
});
});
}).then((updated) => {
// Transaction has been committed
// result is whatever the result of the promise chain returned to the transaction callback
if (updated) {
fs.outputFile(pathToRepoStorage, data, (err) => {
if (err) {
res.sendStatus(500);
} else {
// send repo object
this.io.to(classCode).emit('updated-directory', repo);
res.sendStatus(200);
}
});
} else {
throw new Error();
}
}).catch((err) => {
// Transaction has been rolled back
// err is whatever rejected the promise chain returned to the transaction callback
res.sendStatus(500);
});
}
我收到的信息是:
1 Executing (default): UPDATE "lessons" SET "fileWatched"='/Users/Joshua/Desktop/projects/test_watching',"updatedAt"='2017-02-21 03:51:23.132 +00:00' WHERE "id" = '5'
1 Executing (7d3b44c1-022d-45b5-a873-d09be8726963): START TRANSACTION;
1 Executing (2acc13f0-f351-4c73-b2ee-db1a63c7c460): START TRANSACTION;
1 Executing (7d3b44c1-022d-45b5-a873-d09be8726963): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
1 Executing (2acc13f0-f351-4c73-b2ee-db1a63c7c460): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
1 Executing (7d3b44c1-022d-45b5-a873-d09be8726963): SELECT "id", "name", "lecture", "link", "repo", "fileWatched", "createdAt", "updatedAt", "classId" FROM "lessons" AS "lesson" WHERE "lesson"."id" = '5';
1 Executing (2acc13f0-f351-4c73-b2ee-db1a63c7c460): SELECT "id", "name", "lecture", "link", "repo", "fileWatched", "createdAt", "updatedAt", "classId" FROM "lessons" AS "lesson" WHERE "lesson"."id" = '5';
1 Executing (7d3b44c1-022d-45b5-a873-d09be8726963): UPDATE "lessons" SET "repo"='[{"title":"hahaha","path":"hahaha"}]',"updatedAt"='2017-02-21 03:51:23.189 +00:00' WHERE "id" = '5'
1 Executing (2acc13f0-f351-4c73-b2ee-db1a63c7c460): UPDATE "lessons" SET "repo"='[{"title":"hello","path":"hello"}]',"updatedAt"='2017-02-21 03:51:23.189 +00:00' WHERE "id" = '5'
1 Executing (7d3b44c1-022d-45b5-a873-d09be8726963): COMMIT;
1 Executing (2acc13f0-f351-4c73-b2ee-db1a63c7c460): ROLLBACK;
虽然这确实阻止了我的第二个调用覆盖我的第一个调用,但我的第二个调用被完全忽略,我需要在我的第一个调用完成后立即运行它。
这是我第一次搞乱交易,我似乎找不到很好的文档,对我帮助最大的是
transaction documentation
最佳答案
需要设置 SERIALIZABLE Isolation 来防止这种情况
引用:http://docs.sequelizejs.com/en/v3/api/transaction/
return sequelize.transaction({
isolationLevel: Sequelize.Transaction.SERIALIZABLE
}, function (t) {
// your transactions
}).then(function(result) {
// transaction has been committed. Do something after the commit if required.
}).catch(function(err) {
// do something with the err.
});
关于postgresql - sequelize 更新事务锁行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42358460/