22.6.4 分区和锁定

对于诸如MyISAM之类的存储引擎,它们在执行 DML 或 DDL 语句时实际执行 table 级锁定,在较早版本的 MySQL(5.6.5 和更早版本)中,这种影响分区 table 的语句在整个 table 上施加了锁定;也就是说,所有分区都被锁定,直到语句完成为止。在 MySQL 5.7 中,分区锁修剪在许多情况下消除了不必要的锁,并且大多数读取或更新MyISAM分区 table 的语句只会导致受影响的分区被锁定。例如,分区MyISAMtable 中的SELECT仅锁定那些实际上包含满足SELECT语句的WHERE条件的行的分区。

对于使用诸如InnoDB之类的使用存储引擎影响分区 table 的语句,这些语句采用行级锁定并且实际上在分区修剪之前并不执行(或需要执行)锁定,这不是问题。

接下来的几节将讨论使用 table 级锁的存储引擎对 table 上的各种 MySQL 语句进行分区锁修剪的效果。

对 DML 语句的影响

SELECT语句(包括包含联合或联接的语句)仅锁定那些实际需要读取的分区。这也适用于SELECT ... PARTITION

UPDATE修剪仅针对未更新分区列的 table 锁定。

REPLACEINSERT仅锁定那些要插入或替换行的分区。但是,如果为任何分区列生成AUTO_INCREMENT值,则所有分区都将被锁定。

只要没有更新分区列,就会修剪插入...在重复的密钥更新上

插入...选择仅锁定源 table 中需要读取的那些分区,尽管目标 table 中的所有分区均被锁定。

LOAD DATA语句对分区 table 施加的锁定不能被修剪。

使用分区 table 的任何分区列的BEFORE INSERTBEFORE UPDATE触发器的存在意味着无法修剪更新该 table 的INSERTUPDATE语句的锁定,因为该触发器可以更改其值:在该 table 的任何分区列上的BEFORE INSERT触发器意味着不能修剪由INSERTREPLACE设置的锁,因为BEFORE INSERT触发器可能会在插入行之前更改行的分区列,从而迫使该行进入其他分区。分区列上的BEFORE UPDATE触发器 table 示无法修剪UPDATEINSERT ... ON DUPLICATE KEY UPDATE施加的锁。

受影响的 DDL 语句

CREATE VIEW不会引起任何锁定。

ALTER TABLE ...交换分区修剪锁;仅交换 table 和交换分区被锁定。

ALTER TABLE ...截断分区修剪锁;只有要清空的分区被锁定。

此外,ALTER TABLE语句在 table 级别上获取元数据锁定。

Other statements

LOCK TABLES无法修剪分区锁。

CALL stored_procedure(expr)支持锁定修剪,但不评估* expr *。

DOSET语句不支持分区锁修剪。