19.6.4 分区和锁定

在 MySQL 5.6.5 及更早版本中,对于诸如在执行 DML 或 DDL 语句时实际执行表级锁的存储引擎 MyISAM,这种影响分区表的语句会对整个表施加锁;也就是说,所有分区都被锁定,直到语句完成。MySQL 5.6.6 实现 分区锁修剪,在很多情况下消除了不需要的锁。在 MySQL 5.6.6 及更高版本中,大多数读取或更新分区MyISAM表的语句只会导致受影响的分区被锁定。例如,在 MySQL 5.6.6 之前,SELECT来自分区的MyISAMtable 导致整个表被锁定;在 MySQL 5.6.6 及更高版本中,只有那些实际包含满足 SELECT语句 WHERE条件的行的分区才会被锁定。这具有提高分区MyISAM表并发操作的速度和效率的效果。MyISAM当处理具有许多(32 个或更多)分区的表 时,这种改进变得特别明显 。

这种行为变化不会对使用存储引擎影响分区表的语句产生任何影响,例如 InnoDB使用行级锁定并且在分区修剪之前实际上不执行(或不需要执行)锁。

接下来的几段讨论了分区锁修剪对各种 MySQL 语句对使用表级锁的存储引擎的表的影响。

对 DML 语句的影响

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

UPDATE修剪锁只针对没有更新分区列的表 。

REPLACE现在 INSERT只锁定那些有行要插入或替换的分区。但是,如果AUTO_INCREMENT为任何分区列生成一个值,则所有分区都将被锁定。

INSERT ... ON DUPLICATE KEY UPDATE只要没有更新分区列,就会被修剪。

INSERT ... SELECT现在只锁定源表中需要读取的那些分区,尽管目标表中的所有分区都已锁定。

笔记

INSERT DELAYED分区表不支持。

分区表上的语句强加的锁LOAD DATA 不能被修剪。

存在BEFORE INSERTBEFORE UPDATE使用分区表的任何分区列的触发器意味着 无法删除更新此表的锁INSERT和语句,因为触发器可以更改其值: 表的任何分区列上的触发器意味着由或 不能设置的锁被修剪,因为 触发器可能会在插入行之前更改行的分区列,从而迫使该行进入与其他情况不同的分区。分区列上的 触发器意味着强加的锁或 无法修剪的锁。 UPDATEBEFORE INSERTINSERTREPLACEBEFORE INSERTBEFORE UPDATEUPDATEINSERT ... ON DUPLICATE KEY UPDATE

受影响的 DDL 语句

CREATE VIEW不再导致任何锁定。

ALTER TABLE ... EXCHANGE PARTITION现在修剪锁;只有交换表和交换分区被锁定。

ALTER TABLE ... TRUNCATE PARTITION现在修剪锁;只有要清空的分区被锁定。

ALTER TABLE语句仍然在表级别上使用元数据锁。

其他声明

LOCK TABLES不能修剪分区锁。

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

DOand SET 语句不支持分区锁修剪。