学习总结录 学习总结录
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
首页
归档
分类
标签
  • Java基础
  • Java集合
  • MySQL
  • Redis
  • JVM
  • 多线程
  • 计算机网络
  • 操作系统
  • Spring
  • Kafka
  • Elasticsearch
  • Python
  • 面试专题
  • 案例实践
  • 工具使用
  • 项目搭建
  • 服务治理
  • ORM框架
  • 分布式组件
  • MiniSpring
  • 设计模式
  • 算法思想
  • 编码规范
友链
关于
GitHub (opens new window)
  • Java基础

  • Java集合

  • MySQL

    • MySQL深入01-查询语句
    • MySQL深入02-更新语句
    • MySQL深入03-事务隔离
    • MySQL深入04-深入浅出索引
    • MySQL深入05-全局锁、表锁、行锁
    • MySQL深入06-事务隔离再探
    • MySQL深入07-普通索引和唯一索引
    • MySQL深入08-为什么会选错索引
    • MySQL深入09-字符串字段加索引
    • MySQL深入10-脏页刷新
    • MySQL深入11-数据库表空间回收
    • MySQL深入12-count()
    • MySQL深入13-order by
    • MySQL深入14-正确显示随机消息
    • MySQL深入15-索引失效案例分析
    • MySQL深入16-查询一行数据执行慢
    • MySQL深入17-幻读
    • MySQL深入18-改一行语句锁问题
    • MySQL深入19-暂时提高数据库性能方案
    • MySQL深入20-这么保证数据不丢
    • MySQL深入21-主备一致的保证
    • MySQL深入22-高可用性的保证
    • MySQL深入23-备库延迟好几个小时
    • MySQL深入24-主库出问题,从库这么办
    • MySQL深入25-读写分离的过期读问题
    • MySQL深入26-判断数据库是否出问题
    • MySQL深入27-误删数据的处理方案
    • MySQL深入28-kill不掉的语句
    • MySQL深入29-查询对内存的影响
    • MySQL深入30-join深入
    • MySQL深入31-join语句优化
    • MySQL深入32-临时表深入
    • MySQL深入33-内部临时表何时使用
    • MySQL深入34-InnoDB和Memory
    • MySQL深入35-自增主键为什么不连续
    • MySQL深入36-insert语句的锁
    • MySQL深入37-如何快速复制一张表
    • MySQL深入38-grant和flush privileges
    • MySQL深入39-分区表
      • MySQL深入39-分区表
      • 分区表的引擎层行为
      • 分区表的server层行为
      • 分区表的应用场景
      • 参考
    • MySQL深入40-自增id用完如何处理
  • Redis

  • JVM

  • 多线程

  • 计算机网络

  • Spring

  • Kafka

  • Elasticsearch

  • Python

  • 面试专题

  • 知识库
  • MySQL
旭日
2023-03-31
目录

MySQL深入39-分区表

# MySQL深入39-分区表

为了对分区表的组织形式进行了解,我们先创建一个表t:

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);

image-20220704183944068

在表t中初始化插入了两条记录,按照定义的分区规则,这两行记录分别落在 p_2018 和 p_2019 这两个分区上。

可以看到,这个表包含了一个.frm 文件和 4 个.ibd 文件,每个分区对应一个.ibd 文件。也就是说:

  • 对于引擎层来说,这是 4 个表;
  • 对于 Server 层来说,这是 1 个表。

# 分区表的引擎层行为

上面我们分析过,这个表对于引擎层来说,这是 4 个表,这是为什么呢?

image-20220704184254691

现在假设这个表对于引擎层而言是一个表,那么由于session A的 select 语句对索引 ftime 上这两个记录之间的间隙加了锁。那么在T1时刻,对表t的ftime索引上,加锁状态如下:image-20220704184506885

也就是说,'2017-4-1' 和'2018-4-1' 这两个记录之间的间隙是会被锁住的。那么,sesion B 的两条插入语句应该都要进入锁等待状态。

那么对于session B而言两条插入语句应该都要进入锁等待状态。但是第一条插入语句却能够成功执行,这是因为p_2018 和 p_2019 是两个不同的表,也就是说 2017-4-1 的下一个记录并不是 2018-4-1,而是 p_2018 分区的 supremum。所以 T1 时刻,在表 t 的 ftime 索引上,间隙和加锁的状态其实是图 4 这样的:

image-20220704184708434

由于分区的规则,相当于session A的语句其实只操作了分区p_2018,因此加锁范围就是图中深绿色的部分。所以session B 要写入一行 ftime 是 2018-2-1 的时候是可以成功的,而要写入 2017-12-1 这个记录,就要等 session A 的间隙锁。

# 分区表的server层行为

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

image-20220704185615781

可以看到,虽然 session B 只需要操作 p_2017 这个分区,但是由于 session A 持有整个表 t 的 MDL 锁,就导致了 session B 的 alter 语句被堵住。

通过分区表在server层和引擎层的行为案例的分析,我们小结如下:

  • MySQL 在第一次打开分区表的时候,需要访问所有的分区;
  • 在 server 层,认为这是同一张表,因此所有分区共用同一个 MDL 锁;
  • 在引擎层,认为这是不同的表,因此 MDL 锁之后的执行过程,会根据分区表规则,只访问必要的分区。

# 分区表的应用场景

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

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

# 参考

MySQL 实战 45 讲-极客时间 (opens new window)

#MySQL
上次更新: 2024/06/29, 15:13:44
MySQL深入38-grant和flush privileges
MySQL深入40-自增id用完如何处理

← MySQL深入38-grant和flush privileges MySQL深入40-自增id用完如何处理→

最近更新
01
基础概念
10-31
02
Pytorch
10-30
03
Numpy
10-30
更多文章>
Theme by Vdoing | Copyright © 2021-2024 旭日 | 蜀ICP备2021000788号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式