MySQL 分区表
Posted cpuCode
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 分区表相关的知识,希望对你有一定的参考价值。
mysql 分区表
创建分区表 :
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 个表
引擎层
InnoDB
InnoDB 的分区表加间隙锁 :
session A | session B | |
---|---|---|
T1 | begin; select * from t where ftime = '2017-5-1' for update; | |
T2 | insert into t values('2018-2-1', 1); (Query OK) | |
T3 | insert into t values('2017-12-1', 1); (blocked) |
普通表的间歇锁 :
- sesion B 都会锁住
InnoDB 分区表的间歇锁 :
- sesion B 最后条会锁住
查看锁住信息 :
show engine innodb status
MyISAM
改成 MyISAM 表 :
alter table t engine=myisam
MyISAM分区表的锁 :
- MyISAM 只支持表锁,session A 会锁住表的整个分区
session A | session B | |
---|---|---|
T1 | alter table t engine = myisam; | |
T2 | update 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 不会出现该错误
分区策略 :
- 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 A | session B | |
---|---|---|
T1 | begin; select * from t where ftime = ‘2018-4-1’; | |
T2 | alter table t truncate partition p_2017; (blocked) |
查看执行语句 :
- session A持整表的 MDL 锁,导致 session B 堵住
show processlist;
小结:
- MySQL 在第一次打开分区表时,要访问所有的分区
- server 层,认为同张表,所有分区共用同个 MDL 锁
- 引擎层 : 认为不同表,MDL 锁只锁访问分区
分区表场景
- 用分区表的业务代码更简洁
alter table t drop partition …
: 删除历史数据更快 , 对系统影响小
以上是关于MySQL 分区表的主要内容,如果未能解决你的问题,请参考以下文章