我正在构建一个API,其中一些字段可以递增。
在注意到我的MySQL数据库中的数据不一致之后,我意识到我的代码的第一个版本是错误的:
Answer.incrementVotesCount = async (id) => {
// get a copy of the data
let answer = await getAnswer(id);
// update the copy of the data locally
answer.votesCount++;
// replace the persisted data with the updated copy of the original data
await Answer.updateAll({id}, answer);
};
获取一些数据,在本地更新并持续修改可能会在短时间内多次使用路由时导致一致性问题。
这种情况看起来像这样:
votesCount
等于14。votesCount
等于14。votesCount
变为14 + 1。votesCount
等于15,但来电者B的副本仍然等于14。votesCount
变为14 + 1,而它应该变为15 + 1。已经执行了2个增量,但第二个增加了“压碎”第一个增量,因为它增加了过时的数据。
我想过使用LoopBack3的native SQL功能,但看起来它并不完全可靠,所以我不确定使用它是否是一个好主意(尽管像SET a = a + 1
那样简单的查询应该可以正常工作)。
我还考虑过使用MySQL的触发器来执行一些符合ACID标准的递增,但我不确定我能找到一种干净的方法来实现这一点。
如何在不使其不一致的情况下增加某些数据?
我会把votesCount
字段带到一个单独的hasOne
关系,然后我会使Answer
模型严格='过滤器',所以它会阻止保存不真正属于模型的数据。当采取投票行动时,我会在单独的模型中增加voteCount
,与原来的Answer
无关。
如果您不想这样做,可以尝试检查before save
钩子中的原始值,这样您就可以从db中获取最新值,并将数据库中的votesCount
值与模型中的值进行比较并更新因此。