当写入数据库的并发API调用发生时(或者当服务器速度较慢时)阻止争用条件

让我们想象一下,您将有一个端点用于创build一个用户。 这将是一个平静的应用程序,所以让我们设想一个富客户端调用这个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); } }; 

如果我真的要多次调用这个端点,那么即使您查询了用户表以确保没有重复,也可以在数据库中使用相同的电子邮件创build多个logging。

事实上,我已经设法通过一个我做的压力testing器和一个使用PostgreSQL的节点应用来重新创build这个小实验。

我相信这是一个普遍的问题,但是如何防止这个问题? 我严格限制对某个端点的请求数量,但这似乎不是一个很好的解决scheme。

有任何想法吗? 非常感谢你!

最简单的select是在开始执行查找然后插入的事务的LOCK TABLE "users" IN EXCLUSIVE MODE 。 这确保了一次只有一个事务可以写入表。

为了获得更好的并发性,您可以:

  • 定义emailUNIQUE约束,然后跳过find步骤。 试图insert ,如果失败,陷阱错误和报告重复; 要么

  • 使用其中一种插入 – 如果不存在的技术已知是并发安全的

如果使用唯一约束,需要考虑的一件事就是您的应用可能会将用户标记为禁用而不删除它们,并且可能不希望强制电子邮件地址对于禁用用户是唯一的。 如果是这样,您可能需要部分唯一索引(请参阅文档)。