在非唯一索引列上执行 UPDATE with WHERE 时,表行上下文中的规则如何?
我有一个测试表,其中 col 列作为非唯一索引:
id | col
----------
1 | 1
----------
2 | 2
----------
3 | 2
----------
22 | 3
UPDATE tab SET col=1 WHERE col=1;
// OR
UPDATE tab SET col=3 WHERE col=3;
// OR
UPDATE tab SET col=2 WHERE col=2;
// These updates encounter ONLY rows where col=1, col=3 or col=2
相同的表和相同的更新,但表中多了一条记录,其中 col=2:
id | col
----------
1 | 1
----------
2 | 2
----------
3 | 2
----------
4 | 2
----------
22 | 3
UPDATE tab SET col=1 WHERE col=1;
// OR
UPDATE tab SET col=3 WHERE col=3;
// Both updates encounter ONLY rows where col=1 or col=3.
UPDATE tab SET col=2 WHERE col=2;
// This update encounters ALL the rows in the table even those where col IS NOT 2.
// WHY ?
最佳答案
简而言之,UPDATE
处理过程中遇到的每一行都是独占行锁定的。这意味着 UPDATE
的锁定影响取决于如何处理查询来读取要更新的行。如果您的 UPDATE
查询未使用索引或索引错误,则可能会锁定许多或所有行。 (请注意,锁定行的顺序还取决于所使用的索引。)在您的情况下,由于您的表非常小,并且您正在实质性地更改索引中行的分布,它选择对相关查询使用全表扫描。
您可以通过将大多数 UPDATE
查询转换为 SELECT
并对其使用 EXPLAIN SELECT
来测试它们的性能和行为(在较新的版本中)您甚至可以解释更新
)。
简而言之:在测试性能或锁定行为之前,您应该拥有具有实际数据分布的表,而不是具有一些测试行的非常小的表。
关于MySQL 和 InnoDB - 在非唯一索引上使用 WHERE 进行更新 - 如何遇到行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25099025/