让我们想象一个场景,您将有一个端点用于创建用户。这将发生在一个 Restful 应用程序中,所以让我们想象一下,一个富客户端调用这个 API 端点。
exports.createUser = function(req,res){
if(req.body){
//Check if email has already been used
db.User.find({where:{email:req.body.email}}).success(function(user){
if(user === null || user === undefined){
//Create user
res.send(201);
} else {
res.json(409,{error: 'User already exists'});
}
});
} else {
res.send(400);
}
};
如果我非常快地多次调用此端点,则可以在数据库中使用同一电子邮件创建多个记录,即使您查询用户表以确保不会出现重复也是如此。
我确信这是一个常见问题,但是如何防止这个问题呢?我严格限制对某些端点的请求数量,但这似乎不是一个很好的解决方案。
有什么想法吗? 非常感谢!
最佳答案
最简单的选择是在执行查找然后插入的事务开始时以独占模式锁定表“用户”。这确保一次只能有一个事务写入表。
为了获得更好的并发性,您可以:
对
email
定义一个UNIQUE
约束,然后跳过find
步骤。尝试插入
,如果失败,捕获错误并报告重复;或使用 insert-if-not-exists techniques known to be concurrency-safe 之一
如果使用唯一约束,需要考虑的一件事是您的应用可能会将用户标记为禁用而不删除它们,并且可能不希望强制禁用用户的电子邮件地址是唯一的。如果是这样,您可能需要部分唯一索引(请参阅文档)。
关于javascript - 当发生写入数据库的并发 API 调用时(或者当服务器速度缓慢时),防止竞争情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25296929/