分区表对于引擎层来说,是 多个 个表;对于 Server 层来说,是 1 个表。
包含了一个.frm 文件和 多个 个.ibd 文件,每个分区对应一个.ibd 文件。
分区表的引擎层行为
分区表加间隙锁,只会堵住在这个分区上执行的查询,落到其他分区的查询是不受影响的。
手动分表和分区表
分区表和手工分表,一个是由 server 层来决定使用哪个分区,一个是由应用层代码来决定使用哪个分表。因此,从引擎层看,这两种方式也是没有差别的。
两个方案的区别,主要是在 server 层上。分区表一个被广为诟病的问题:每当第一次访问一个分区表的时候,MySQL 需要把所有的分区都访问一遍。
MyISAM 分区表使用的分区策略,我们称为通用分区策略(generic partitioning),每次访问分区都由 server 层控制。通用分区策略,是 MySQL 一开始支持分区表的时候就存在的代码,在文件管理、表管理的实现上很粗糙,因此有比较严重的性能问题。(mysql 8.0开始已经弃用了)
InnoDB 引擎引入了本地分区策略(native partitioning),是在 InnoDB 内部自己管理打开分区的行为。
分区表的 server 层行为
如果从 server 层看的话,一个分区表就只是一个表。分区表在做 DDL 的时候,共用一个MDL锁。如果使用的是普通分表,那么当你在 truncate 一个分表的时候,肯定不会跟另外一个分表上的查询语句,出现 MDL 锁冲突。
小结一下:
1)MySQL 在第一次打开分区表的时候,需要访问所有的分区;
2)在 server 层,认为这是同一张表,因此所有分区共用同一个 MDL 锁;
3)在引擎层,认为这是不同的表,MDL 锁之后的执行过程,会根据分区表规则只访问必要的分区。
如果查询语句的 where 条件中没有分区 key,那就只能访问所有分区了。
分区表的应用场景
1)分区表的一个显而易见的优势是对业务透明,相对于用户分表来说,使用分区表的业务代码更简洁
2)分区表可以很方便的清理历史数据。如果一项业务跑的时间足够长,往往就会有根据时间删除历史数据的需求。这时候,按照时间分区的分区表,就可以直接通过 alter table t drop partition ... 这个语法删掉分区,从而删掉过期的历史数据。
3)alter table t drop partition ... 操作是直接删除分区文件,效果跟 drop 普通表类似。与使用 delete 语句删除数据相比,优势是速度快、对系统影响小。




