处理来自不同用户的并发 MySQL 查询
我有一个 PHP/MySQL 注册系统,它限制了可以注册某项内容的人数。假设有 5 个空位,其中 4 个已满。现在,登录的 2 个不同用户同时提交了一个表单,该表单执行 MySQL 查询以将该人添加到列表中。
简化后,PHP 逻辑看起来像这样:
if($numberOfSpotsTaken < 5) {
//add user to list
}
else {
//don't add user to list
}
现在,因为用户同时提交请求,所以当代码检查有多少名额被占用时,两个用户的名额都将低于 5。最终发生的情况是,两个请求都通过了,当限制应该为 5 时,最终有 6 个人出现在列表中。
如何防止这种情况,以便两个(或更多)用户在同一时间提交请求同一时间无法突破人数限制?
I have a PHP/MySQL sign-up system that limits the number of people who can sign up for something. So, let's say there are 5 spots available, and 4 of them are already full. Now, 2 different users who are logged in submit a form at the exact same time that executes a MySQL query to add that person to the list.
Simplified, the PHP logic looks something like:
if($numberOfSpotsTaken < 5) {
//add user to list
}
else {
//don't add user to list
}
Now, because the users both submit the request at the same time, when the code checks to see how many spots are taken, it will be under 5 for both. What ends up happening is that both requests go through and 6 people end up on the list when the limit is supposed to be 5.
How can I prevent this situation so that two (or more) users who submit a request at the same time can't bypass the limit of how many people can sign up?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我通过使用 PDO 的
beginTransaction()
、rollBack()
和commit()
方法来防止超额预订,从而解决了这个问题。简单地说,这就是我所做的:
I was able to solve this problem by using PDO's
beginTransaction()
,rollBack()
, andcommit()
methods to prevent overbooking.Simplified, here's what I did:
MySQL 只允许单个用户一次写入单个数据库。
我建议您检查页面加载和提交。如果您不检查服务器端的所有内容(用户提交的数据、可用性等),那么您的脚本就会非常不安全。
如果您真的认为有人可能会在几微秒内溜进来,请在“成功”后检查脚本以查看有多少条目。如果太多,请删除最新条目,直至正确的数量。
确保你这么想并处理任何错误:D
MySQL only allows a single user to write to a single database at a single time.
I would recommend that you check on page load AND on submission. If you are not checking everything (user submitted data, availability, etc) server-side, then you're going to make your scripts very insecure.
If you really really think somebody might slip in in a few microseconds, then have the script check after 'success' to see how many entries there are. If there are too many, remove the latest entries down to the correct number.
Make sure you think this though and handle any errors :D
我去找你的答案,发现了这个:
事务数据库锁定
I went looking for an answer for you and found this:
Transactional DB Locking
从技术上讲,您的情况可能会发生,但这几乎是不可能的。 MySQL 确实允许多次插入,这就是获取独占锁的用武之地。请参阅此处的 MySQL 文档。 http://dev.mysql.com/doc/refman /5.0/en/innodb-locks-set.html
Technically your scenario can happen, but it's almost impossible. MySQL does allow multiple inserts which is where obtaining an exclusive lock comes in. See MySQL's documentation here. http://dev.mysql.com/doc/refman/5.0/en/innodb-locks-set.html