InnoDB 是否锁定整个 table 用于使用组合键的一部分的删除?

Does InnoDB lock the whole table for a delete which uses part of a composed key?

我有一个 MySQL table(称之为 'my_table'),它有一个包含 4 列的组合主键(称之为 'a'、'b'、 'c' 和 'd').

至少有一次我在并行异步 EJB 调用上遇到死锁,调用 'DELETE FROM my_table where a=?和 b=?' 具有不同的值,所以我开始研究 InnoDB table 锁定是如何工作的。

我没有找到关于 table 锁定如何使用组合键的明确文档。整个 table 是否被删除锁定,尽管实际删除的行之间没有重叠?

我是否需要执行 select 来恢复 c 和 d 的值并使用整个主键删除批次?

这是在使用 4 个不同数据库的复杂应用程序的上下文中。只有 MySQL 似乎有这个问题。

InnoDB 从不为 DML 语句锁定整个 table。 (除非 DML 命中所有行。)

DDL语句还有其他的锁,比如当ALTER TABLE是modifying/addingcolumns/indexes/etc。 (其中一些在 MySQL 8.0 中已大大加快。)

关于锁定的复合键没有什么特别之处。

有一种东西叫做"gap lock"。由于各种原因,索引中两个值之间的 "gap" 将被锁定。这可以防止潜在的冲突,例如插入尚不存在的相同 new 值,并且存在唯一性约束。

由于 PRIMARY KEY 是唯一键,您 可能 遇到了类似的问题。

如果可行,做SHOW ENGINE INNODB STATUS;看锁是否"gap"。

另一件可能发生的事情是,锁可能开始变弱,然后升级到 "eXclusive"。这可能会导致死锁。

Do I need to do a select to recover the values for c and d and delete batches using the whole primary key?

我认为你需要更准确地解释你在做什么。提供查询。提供 SHOW CREATE TABLE.

InnoDB 的锁处理可能是 MySQL 独有的。它有一些怪癖。有时它对锁定的内容有点贪心;作为补偿,它可能比竞争对手更快。

无论如何,检查死锁(和超时)并处理它们。希望这些问题很少见,因此处理它们不会造成太大的性能负担。

DELETE FROM my_table where a=? and b=? 表示可能正在删除大量行。这意味着撤消日志和 MVCC 需要做很多工作。因此,我建议尽量不要一次删除(或更新)超过 1K 行。