分区和锁定
对于像MyISAM这样的存储引擎,在执行DML或DDL语句时实际上会执行表级别的锁,在旧版本的MySQL(5.6.5及更早的版本)中,这样的语句会影 响分区表,并对整个表施加锁;也就是说,所有分区都被锁定,直到语句完成。在MySQL 5.7中,分区锁修剪在很多情况下消除了不必要的锁, 大多数读取或更新分区的MyISAM表的语句只会锁定受影响的分区。例如,一个分区的MyISAM表的SELECT只锁定那些实际上包含满足SELECT语句 WHERE条件的行的分区。
对于使用存储引擎(如InnoDB)来影响分区表的语句来说,这不是问题。InnoDB采用行级锁,在分区修剪之前实际上不执行(或需要执行)锁。
接下来的几段将讨论分区锁修剪对使用存储引擎(使用表级锁)的各种MySQL语句的影响。
对DML语句的影响
SELECT语句(包括那些包含union或join的语句)只锁定那些实际需要读取的分区。这也适用于SELECT … PARTITION。
UPDATE只对没有更新分区列的表进行锁修剪。
REPLACE和INSERT只对那些有要插入或替换行的分区锁定。但如果对任何分区列生成了AUTO_INCREMENT值,那么所有分区都会被锁定。
只要未更新分区列,INSERT… ON DUPLICATE KEY UPDATE 就会被修剪。
INSERT … SELECT只锁定源表中需要读取的那些分区,尽管目标表中的所有分区都是锁定的。
不能修剪由LOAD DATA语句对分区表施加的锁。
在使用分区表的任何分区列时,存在BEFORE INSERT或BEFORE UPDATE触发器,这意味着更新表的INSERT和UPDATE语句上的锁不能被修剪,因为触 发器可以修改其值:在表的任何分区列上都有一个BEFORE INSERT触发器,这意味着由INSERT或REPLACE设置的锁不能被修剪,因为BEFORE INSERT触发器可能会在插入行之前更改该行的分区列,从而迫使该行进入不同的分区。分区列上的BEFORE UPDATE触发器意味着UPDATE或 INSERT… ON DUPLICATE KEY UPDATE无法被修剪。
受影响的DDL语句
CREATE VIEW不会引起任何锁。
ALTER TABLE … EXCHANGE PARTITION修剪锁;只有交换的表和交换的分区被锁定。
ALTER TABLE … TRUNCATE PARTITION修剪锁;只有要清空的分区被锁定。
此外,ALTER TABLE语句在表级别上获取元数据锁。
其它语句
LOCK TABLES不能修剪分区锁。
CALL stored_procedure(expr)支持锁修剪,但是对expr进行评估却没有。
DO和SET语句不支持分区锁修剪。