分区表有什么问题,为什么公司规范不让使用分区表呢?
什么是分区表
在示例表插入两条记录,按分区规则,记录分别落在p_2018和p_2019分区。
可见,该表包含了一个.frm
文件和4个.ibd
文件,每个分区对应一个.ibd
文件:
- 对于引擎层,这是4个表
- 对于Server层,这是1个表
分区表的引擎层行为
举个在分区表加间隙锁的例子,目的是说明对于InnoDB来说,这是4个表。
- 分区表间隙锁
session_1 | session_2 | |
T1 | begin; select * from tt where ftime=‘2017-5-1’ for update; |
|
T2 | insert into tt values (‘2018-2-1’, 1); (Query OK) insert into tt values (‘2017-12-1’, 1); (阻塞) |
初始化表tt时,只插入两行数据。session1的select语句对索引ftime上这两个记录之间的间隙加了锁。如果是一个普通表的话,T1时刻,在表t的ftime索引上,间隙和加锁状态应该如下
- 普通表的加锁范围
即‘2017-4-1’ 和’2018-4-1’ 这两个记录之间的间隙会被锁住。
那sesion2的两条插入语句应该都要进入锁等待状态。
但session2的第一个insert成功。因为对于引擎,p_2018和p_2019是两个不同表,即2017-4-1的下一个记录并不是2018-4-1,而是p_2018分区的supremum。
所以T1,在表t的ftime索引上,间隙和加锁的状态其实:
- 分区表tt的加锁范围
由于分区表规则,session1的select只操作了分区p_2018,因此加锁范围就是上图绿色。
所以,session2写2018-2-1成功,而要写2017-12-1,就要等session1的间隙锁。
这时show engine innodb status的部分结果:
- session2被锁住信息
MyISAM分区表
# 把表tt改成MyISAM表 alter table t engine=myisam
对于MyISAM引擎来说,这是4个表。
- 用MyISAM表锁验证
session_1 | session_2 |
alter table t engine=myisam; update tt set c=sleep(100) where ftime=‘2017-4-1’; |
|
select * from tt where ftime=‘2018-4-1’; (Query OK) select * from tt where ftime=‘2017-5-1’; (阻塞) |
在session1,sleep(100)将该语句的执行时间设为100s。由于MyISAM引擎只支持表锁,所以这条update语句会锁住整个表tt上的读。
但session2的第一条查询语句可以正常执行,第二条语句才进入锁等待。
因为MyISAM的表锁实现在引擎层,session1加的表锁,其实是锁在分区p_2018。因此,只会堵住在这个分区上执行的查询,其他分区查询不受影响。
分区表使用起来看来挺好使的呀,为啥禁用?
使用分区表的一个重要原因就是单表过大。那若不使用分区表,就要手动分表。