分区表有什么问题,为什么公司规范不让使用分区表呢?

什么是分区表


在示例表插入两条记录,按分区规则,记录分别落在p_2018p_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。因此,只会堵住在这个分区上执行的查询,其他分区查询不受影响。

分区表使用起来看来挺好使的呀,为啥禁用?
使用分区表的一个重要原因就是单表过大。那若不使用分区表,就要手动分表。

手动分表 V.S 分区表

比如,按年份划分,分别创建普通表t_2017t_2018t_2019等。手工分表也要找到需要更新的所有分表,然后依次执行更新。
性能上和分区表没有差别。

  • 分区表由server层决定使用哪个分区
  • 手动分表由应用层代码决定使用哪个分表

所以从引擎层看,也没啥区别。

两种方式的区别,主要在server层。server层的分区表一个严重问题就是打开表的行为。

分区策略

第一次访问一个分区表时,MySQL需要把所有分区都访问一遍。
一个典型的报错场景:若一个分区表的分区很多,比如超过1000,而MySQL启动时,open_files_limit参数默认值1024,则在访问该表时,由于需要打开所有文件,导致打开表文件的个数超过了上限而报错。

比如对一个包含很多分区的表,执行insert直接报错:

这条insert其实只需要访问一个分区,但语句报错了。这个表是MyISAM,如果使用InnoDB,不会出现该问题。

MyISAM分区表使用通用分区策略(generic partitioning),每次访问分区都由server层控制。通用分区策略,是MySQL一开始支持分区表的时候就存在的代码,在文件管理、表管理的实现上很粗糙,性能问题很严重。

MySQL 5.7.9开始,InnoDB引入本地分区策略(native partitioning),在InnoDB内部自己管理打开分区的行为。

MySQL 5.7.17开始,将MyISAM分区表标记为deprecated。
MySQL 8.0开始,已经禁止创建MyISAM分区表,只允许创建已经实现了本地分区策略的引擎。

目前只有InnoDB和NDB引擎支持本地分区策略。

分区表的server层行为

对于server层,一个分区表就只是一个表。

如图,分别是该例的操作序列和执行结果图。

  • 分区表的MDL锁
session_1 session_2
begin;
select * from tt
where ftime=‘2018-4-1’;
alter table tt truncate partition p_2017
(阻塞)


  • show processlist

    虽然session2只需操作p_2107分区,但因为session1持有整个表tt的MDL锁,导致session2的alter语句被阻塞。

所以分区表在做DDL时,影响会更大。若使用的普通分表,则当你在truncate一个分表时,肯定不会跟另外一个分表上的查询语句,出现MDL锁冲突。

小结

在server层,认为这是同一张表,因此所有分区共用同一MDL锁
在引擎层,认为这是不同表,因此MDL锁之后的执行过程,会根据分区表规则,只访问必要的分区。

什么是必要的分区
根据SQL语句中的where条件,结合分区规则。比如上面的where ftime=‘2018-4-1’,根据分区规则year函数算出来的值是2018,那么就会落在p_2019分区。

但若这个where 条件改成 where ftime>='2018-4-1',虽然查询结果相同,但这时根据where条件,就要访问p_2019p_others俩分区。

若查询语句的where条件没有分区key,就只能访问所有分区了。当然,这并非分区表的问题。即使是使用业务分表,where条件中没有使用分表的key,也必须访问所有的分表。

分区表的应用场景

一大优势是对业务透明,相对于用户分表来说,使用分区表的业务代码更简洁。还有,分区表可以很方便的清理历史数据。

如果一项业务跑的时间足够长,往往就会有根据时间删除历史数据的需求。这时按时间分区的分区表,就可直接通过alter table t drop partition …这个语法删掉分区,从而删掉过期的历史数据。

alter table t drop partition …是直接删除分区文件,跟drop普通表类似。与delete相比,优势是速度快、对系统影响小。

需要注意的是,我是以范围分区(range)为例和你介绍的。实际上,MySQL还支持hash分区、list分区等分区方法。
实际使用时,分区表跟用户分表,有两个问题:

  • 第一次访问时,需要访问所有分区
  • 共用MDL锁

因此,如果要使用分区表,就不要创建太多分区。我见过一个用户做了按天分区策略,然后预先创建了10年的分区。这种情况下,访问分区表的性能自然是不好的。这里有两个问题:

  • 分区并不是越细越好
    单表或单分区的数据一千万行,只要没有特别大的索引,对于现在的硬件能力来说都已是小表
  • 分区不要提前预留太多,在使用之前预先创建即可
    比如,如果是按月分区,每年年底时再把下一年度的12个新分区创建上即可。对于没有数据的历史分区,及时drop

分区表的其他问题,比如查询需要跨多个分区取数据,查询性能就会比较慢,基本上就不是分区表本身的问题,而是数据量或说使用方式问题。
如果你的团队已经维护了成熟的分库分表中间件,用业务分表,对业务开发同学没有额外的复杂性,对DBA也更直观,自然更好。

为什么阿里不推荐使用MySQL分区表?相关推荐

  1. 阿里云可以外链mysql_案例详细说明阿里云下设置MySQL远程连接步骤

    软件安装:装机软件必备包 SQL是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言.在使用它时,只需要发出& ...

  2. 阿里云rds for mysql平台介绍_阿里云RDS for MySQL 快速入门——笔记

    1初始化配置 1.1设置白名单 创建RDS实例后,需要设置RDS实例的白名单,以允许外部设备访问该RDS实例.默认的白名单只包含默认IP地址127.0.0.1,表示任何设备均无法访问该RDS实例. 设 ...

  3. 【mysql安装】阿里云centos7环境mysql安装

    阿里云centos7环境mysql安装 正文开始@Assassin 目录: 阿里云centos7环境mysql安装 一. 环境说明: 1.1 操作系统: 1.2 MySQL版本: 1.3 安装方式: ...

  4. 阿里云mysql宽带_阿里云数据库RDS MySQL版购买使用详细过程

    阿里云数据库 RDS MySQL 版如何购买使用?通过前面学习如何选择阿里云数据库 RDS MySQL 版,魏艾斯博客已经阿里云 MySQL 有了初步认识,接下来跟着老魏一起购买使用阿里云数据库 RD ...

  5. mysql表分区数量限制_详解MySQL分区表的局限和限制的代码实例

    本文对Mysql分区表的局限性做了一些总结,因为个人能力以及测试环境的 原因,有可能有错误的地方,还请大家看到能及时指出,当然有兴趣的朋友可以去官方网站查阅. 禁止构建 分区表达式不支持以下几种构建: ...

  6. 阿里云mysql容量_阿里云RDS的mysql数据库占用空间超过90%的处理

    阿里云RDS数据库最大支持2T,目前已经占用了90%,如果进行分库或者迁移比较麻烦,思路是找出占用空间过大的日志或不重要的文件进行删除操作 查询所有数据库占用磁盘空间大小的SQL语句: show bi ...

  7. 【推荐】MySQL Cluster报错及解决方法(不断更新中)

    排查问题技巧: MySQL Cluster 自带了一个错误代码的查看的小程序.通过这个小东西我们可以方便的定位问题的原因. 这个程序就是 perror 在MYSQL安装目录的bin下面. 如报错:ER ...

  8. 阿里云推荐码:8N6TBT

    2019独角兽企业重金招聘Python工程师标准>>> 阿里云推荐码:8N6TBT 转载于:https://my.oschina.net/u/1468119/blog/783718

  9. 阿里云推荐引擎使用教程

    2019独角兽企业重金招聘Python工程师标准>>> 产品概述: 推荐引擎(Recommendation Engine,以下简称RecEng,特指阿里云推荐引擎)是在阿里云计算环境 ...

  10. mysql 分区表 归档_MySQL分区表

    1,MySQL分区表作用 当单表的数据量较大,需要进行定期的数据归档删除时,或者提高查询性能,都可以采用分区: 2,分区表设置 分区的种类 range分区 list分区 hash分区 key分区 ra ...

最新文章

  1. ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml)
  2. 2-4+并发的优势与风险
  3. spring+mybatis 多数据源整合
  4. Python入门100题 | 第027题
  5. 关于Github的那点事儿
  6. 前端学习(927):淘宝flexiblejs源码分析之pageshow原理
  7. Netty工作笔记0004---BIO简介,介绍说明
  8. 直角三角形 纪中 1385 数学_斜率 英文题解
  9. PHP文件上传实现的注意点
  10. tcp和icmp测速哪个好_ping icmp和tcp区别:
  11. 泰坦尼克号数据集处理
  12. CAD .Net 开发-快速入门
  13. 加拿大签证材料(一家三口)
  14. 完全免费的Windows代码签名证书(大神勿喷)
  15. 扩增子分析流程 —— 数据处理(vsearch)
  16. 自带作弊功能的老虎机--一样会让你输光,呵呵
  17. 分位数Granger因果检验实现原理
  18. 谈国际政治经济与升斗小民
  19. 硬盘分区出错提示磁盘结构损坏且无法读取怎么修复??
  20. 面试题整理|50个React面试题及解析

热门文章

  1. jquery选择器篇
  2. jenkins 版本升级
  3. Linux面试题史上最全总结
  4. 计算机网络未识别网络,电脑网络出现未识别的网络,无Internet访问的解决办法...
  5. 计算机专业自主招生有哪些学校,自主招生的学校类型有哪些
  6. The “fxp/composer-asset-plugin“ plugin was skipped because it requires a Plugin API version (“^1.0“)
  7. LiveZilla 3.2.0.2的汉化包
  8. 禁用/开启 Windows系统3D加速
  9. SitePoint Podcast#167:炉边聊天
  10. PhalApi 事务操作