22.6.4 分区和锁定
对于诸如MyISAM之类的存储引擎,它们在执行 DML 或 DDL 语句时实际执行 table 级锁定,在较早版本的 MySQL(5.6.5 和更早版本)中,这种影响分区 table 的语句在整个 table 上施加了锁定;也就是说,所有分区都被锁定,直到语句完成为止。在 MySQL 5.7 中,分区锁修剪在许多情况下消除了不必要的锁,并且大多数读取或更新MyISAM
分区 table 的语句只会导致受影响的分区被锁定。例如,分区MyISAM
table 中的SELECT仅锁定那些实际上包含满足SELECT
语句的WHERE
条件的行的分区。
对于使用诸如InnoDB之类的使用存储引擎影响分区 table 的语句,这些语句采用行级锁定并且实际上在分区修剪之前并不执行(或需要执行)锁定,这不是问题。
接下来的几节将讨论使用 table 级锁的存储引擎对 table 上的各种 MySQL 语句进行分区锁修剪的效果。
对 DML 语句的影响
SELECT语句(包括包含联合或联接的语句)仅锁定那些实际需要读取的分区。这也适用于SELECT ... PARTITION
。
UPDATE修剪仅针对未更新分区列的 table 锁定。
REPLACE和INSERT仅锁定那些要插入或替换行的分区。但是,如果为任何分区列生成AUTO_INCREMENT
值,则所有分区都将被锁定。
只要没有更新分区列,就会修剪插入...在重复的密钥更新上。
插入...选择仅锁定源 table 中需要读取的那些分区,尽管目标 table 中的所有分区均被锁定。
LOAD DATA语句对分区 table 施加的锁定不能被修剪。
使用分区 table 的任何分区列的BEFORE INSERT
或BEFORE UPDATE
触发器的存在意味着无法修剪更新该 table 的INSERT
和UPDATE
语句的锁定,因为该触发器可以更改其值:在该 table 的任何分区列上的BEFORE INSERT
触发器意味着不能修剪由INSERT
或REPLACE
设置的锁,因为BEFORE INSERT
触发器可能会在插入行之前更改行的分区列,从而迫使该行进入其他分区。分区列上的BEFORE UPDATE
触发器 table 示无法修剪UPDATE
或INSERT ... ON DUPLICATE KEY UPDATE
施加的锁。
受影响的 DDL 语句
CREATE VIEW不会引起任何锁定。
ALTER TABLE ...交换分区修剪锁;仅交换 table 和交换分区被锁定。
ALTER TABLE ...截断分区修剪锁;只有要清空的分区被锁定。
此外,ALTER TABLE语句在 table 级别上获取元数据锁定。
Other statements
LOCK TABLES无法修剪分区锁。
CALL stored_procedure(expr)支持锁定修剪,但不评估* expr
*。