【问题标题】:Which records are locked with MySQL's 'SELECT ... FOR UPDATE'哪些记录被 MySQL 的 'SELECT ... FOR UPDATE' 锁定
【发布时间】:2014-01-25 08:34:31
【问题描述】:

我已经阅读并测试过 MySQL 的 InnoDB 中的行级锁,但我仍然觉得很难说“我知道 MySQL 中的锁是如何工作的”!

这是我的测试数据:

mysql> select * from lockable;
+----+----+----+
| id | c1 | c2 |
+----+----+----+
|  1 | A  | A  |
|  2 | A  | B  |
|  3 | A  | C  |
|  4 | B  | A  |
|  5 | B  | B  |
|  6 | B  | C  |
|  7 | C  | A  |
|  8 | C  | B  |
|  9 | C  | C  |
+----+----+----+
9 rows in set (0.00 sec)

为了测试 MySQL 关于行级锁的行为,我打开了两个终端并连接到 MySQL。我要把它们命名为mysql1>mysql2>。这是我在第一个终端上执行的操作:

mysql1> ROLLBACK;
mysql1> BEGIN;
mysql1> SELECT id, c1, c2 FROM lockable WHERE c1 = "A" FOR UPDATE;
+----+----+----+
| id | c1 | c2 |
+----+----+----+
|  1 | A  | A  |
|  2 | A  | B  |
|  3 | A  | C  |
+----+----+----+
3 rows in set (0.00 sec)

然后在第二个终端上:

mysql2> SELECT * FROM lockable WHERE c1 = "B" FOR UPDATE;

令我惊讶的是,上面的查询会被第一个查询阻止!于是我回滚了第一个终端,重新开始:

mysql1> ROLLBACK;
mysql1> BEGIN;
mysql1> SELECT id, c1, c2 FROM lockable LIMIT 3 FOR UPDATE;
+----+----+----+
| id | c1 | c2 |
+----+----+----+
|  1 | A  | A  |
|  2 | A  | B  |
|  3 | A  | C  |
+----+----+----+
3 rows in set (0.00 sec)

然后在第二个终端上:

mysql2> SELECT * FROM lockable WHERE LIMIT 6,1  FOR UPDATE;

第二个终端又被第一个屏蔽了!是否存在并非表的所有记录都被锁定的情况?如果不是,为什么称为“行级锁定”?

【问题讨论】:

  • 不相关但:在标准 SQL 中,双引号用于标识符。要指定字符串文字,请使用单引号。 "B" 是列名,但 'B' 是字符串值。 MySQL 接受错误和正确的书写方式,但如果您想使用不同的 DBMS,您应该坚持使用符合标准的方式。关于您的问题:我认为(不确定)您受到 MySQL 的“间隙锁定”的影响,它锁定了其他行,而不仅仅是您请求的行。您可能还想尝试使用真正的update。也许select .. for update 的行为有所不同。
  • 感谢您的帖子,从现在开始我将尝试使用' 而不是"
  • 顺便说一句:您的示例在 Postgres 和 Oracle 中按预期工作。
  • 我也设法让它在 MySQL 中工作。我会尽快发布答案。

标签: mysql innodb rowlocking


【解决方案1】:

我的问题的答案在MySQL's manual说:

锁定读取、UPDATE 或 DELETE 通常会设置记录锁定 在 SQL 处理过程中扫描的每条索引记录 声明。

因此,锁定应用于遍历期间被扫描的记录,而不是所有记录。如果没有找到索引,则完成完整扫描并锁定所有记录。所以我需要在列上设置一个索引。即使在到达目标记录时读取了某些记录,它们也会被锁定(即使它们最终可能没有被选中)。

【讨论】:

    猜你喜欢
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    相关资源
    最近更新 更多