【问题标题】:How to manage concurrency in mysql?如何在mysql中管理并发?
【发布时间】:2016-07-19 20:58:02
【问题描述】:

我被这个困住了。为了简单起见,假设我有这张桌子

CREATE TABLE IF NOT EXISTS `tbl_bags_oranges` (
  `idbag` int(11) NOT NULL AUTO_INCREMENT,
  `n_oranges` int(11) NOT NULL,
  PRIMARY KEY (`idbag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci AUTO_INCREMENT=1 ;

我正在开发一个 php 脚本来代表用户抢橘子的情况。这就是我正在做的:

  1. 我使用SELECT 检查给定的 idgab 中是否有橘子 (n_oranges > 0)
  2. 如果是这样,我 UPDATE 将表格减去 1 到 n_oranges

但是当袋子里只有一个橙子时,可能会发生以下情况:

  1. 用户 A 想要拿一个橙子。 'SELECT' 表示只有一个橙色。
  2. 用户 B 想要拿一个橙子。 'SELECT' 表示只有一个橙色。
  3. 用户 A 拿起橘子。我UPDATE 表,现在 n_oranges = 0。
  4. 用户 B 能够抢到橙子,因为他的 SELECT 说有一个橙子。

我该如何解决这个问题?交易? LOCK TABLES?由于我无法检查这种情况,因此无法知道我做得好还是坏。

【问题讨论】:

  • 做一个intention lock。你的会有点相似,但会有所减少。瞬间,安全。
  • 您是否尝试在一步更新之前再次添加检查 n_oranges?

标签: php mysql concurrency


【解决方案1】:

您可以使用locking reads。 详细:

  • 确保 autocommit 已禁用
  • START TRANSACTION
  • SELECT ... FROM tbl_bags_oranges WHERE ... FOR UPDATE
  • 在代码中执行您需要执行的任何其他操作
  • 保存新值UPDATE tbl_bags_oranges SET ...
  • COMMIT

在这种情况下,在您的场景中,第二个查询将阻塞,直到第一个事务提交,因此不会发生竞争条件

【讨论】:

  • 这正是我想要的。非常感谢!
【解决方案2】:

您可以在更新表格时进行检查,如下所示:

UPDATE `tbl_bags_oranges`
SET n_oranges=n_oranges-1 
WHERE n_oranges>=1;

您可以根据自己的情况修改代码。

【讨论】:

  • 对不起,我的错。我希望这个问题尽可能简单明了,但我没有意识到我的例子太简单了。实际上,我必须检查 3 个不同表中的值,然后更新其中一个。
猜你喜欢
  • 2016-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 2018-12-28
  • 1970-01-01
相关资源
最近更新 更多