zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

MySQL 分区表

mysql 分区表
2023-09-14 09:14:49 时间

创建分区表 :

CREATE TABLE `t` (
  `ftime` datetime NOT NULL,
  `c` int(11) DEFAULT NULL,
  KEY (`ftime`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
PARTITION BY RANGE (YEAR(ftime))
(PARTITION p_2017 VALUES LESS THAN (2017) ENGINE = InnoDB,
 PARTITION p_2018 VALUES LESS THAN (2018) ENGINE = InnoDB,
 PARTITION p_2019 VALUES LESS THAN (2019) ENGINE = InnoDB,
PARTITION p_others VALUES LESS THAN MAXVALUE ENGINE = InnoDB);

insert into t values('2017-4-1',1),('2018-4-1',1);

该表有一个 .frm 和 4 个 .ibd :

  • 对引擎 : 有 4 个表
  • 对 Server : 有 1 个表

image.png

引擎层

InnoDB

InnoDB 的分区表加间隙锁 :

session Asession B
T1begin;
select * from t where ftime = '2017-5-1' for update;
T2insert into t values('2018-2-1', 1); (Query OK)
T3insert into t values('2017-12-1', 1); (blocked)

普通表的间歇锁 :

  • sesion B 都会锁住

image.png

InnoDB 分区表的间歇锁 :

  • sesion B 最后条会锁住

image.png

查看锁住信息 :

show engine innodb status

image.png

MyISAM

改成 MyISAM 表 :

alter table t engine=myisam

MyISAM分区表的锁 :

  • MyISAM 只支持表锁,session A 会锁住表的整个分区
session Asession B
T1alter table t engine = myisam;
T2update t set c= sleep(100) where ftime=‘2017-4-1’;
select * from t where ftime = ‘2018-4-1’; (Query OK)
select * from t where ftime = ‘2017-5-1’; (blocked)

手动分表和分区表区别 :

  • 手工分表 : 按年份创建表。性能无差别
  • 分区表 : 由 server 层决定用哪个分区,手工分表 : 由应用代码决定用哪个分表

分区策略

MySQL 第一次访问一个分区表时,会把所有的分区都访问一遍

典型报错 :

  • open_files_limit的默认 : 1024 , 当打开文件超过该上限就报错
  • InnoDB 不会出现该错误

image.png

分区策略 :

  • MyISAM 分区表用 : 通用分区策略 (generic partitioning) : 每次访问分区由 server 层控制
  • MySQL 5.7.9 后 : InnoDB 引入本地分区策略 (native partitioning) : 呦 InnoDB 管理打开分区
  • MySQL 5.7.17 后 : MyISAM 分区表标记为即将弃用 (deprecated) : 从该版本开始不建议用,并找替代方案
  • MySQL 8.0后 : 不准创建 MyISAM 分区表,只能创建本地分区策略的引擎。只有 InnoDB 和 NDB 引擎支持本地分区策

server层

分区表 MDL锁 :

session Asession B
T1begin;
select * from t where ftime = ‘2018-4-1’;
T2alter table t truncate partition p_2017; (blocked)

查看执行语句 :

  • session A持整表的 MDL 锁,导致 session B 堵住
show processlist;

image.png

小结:

  • MySQL 在第一次打开分区表时,要访问所有的分区
  • server 层,认为同张表,所有分区共用同个 MDL 锁
  • 引擎层 : 认为不同表,MDL 锁只锁访问分区

分区表场景

  • 用分区表的业务代码更简洁
  • alter table t drop partition … : 删除历史数据更快 , 对系统影响小