数据库内核月报 - 2015 / 08-MySQL · 社区动态 · InnoDB Page Compression

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介:

背景:Punch hole和Sparse file

Punch hole是一个需要操作系统和文件系统支持的特性,顾名思义就是在文件中打洞。这个特性的目的是为了减少数据文件的磁盘开销。比如一个大文件中有一部分数据我们是不需要的,就可以通过punch hole特性将其删除,相当于在文件中打了个洞,这个洞是不占用磁盘的。

Punch hole特性通过fallocate调用来实现,在其第二个参数指定flag FALLOC_FL_PUNCH_HOLE时,第三个参数指定需要punch hole的偏移位置,第四个参数指定punch hole的长度。当成功打洞后,以后访问到这个范围的数据都返回0。

fallocate的描述见文档。根据文档的描述,FALLOC_FL_PUNCH_HOLE 需要和另外一个flag FALLOC_FL_KEEP_SIZE 一起使用,也就是说,即使在文件中打洞,通过stat获得的文件大小也不会发生变化,你需要通过du命令来获得准确的磁盘文件大小。

目前不是所有的内核都支持该特性,在阿里环境需要使用rh6 2.6.32-358及之后的版本,另外由于对应的flag 宏没有定义,我们需要显式的定义如下两个宏:(感谢 @伯瑜 大神的指点)

#define FALLOC_FL_PUNCH_HOLE    0x02 /* de-allocates range */
#define FALLOC_FL_KEEP_SIZE     0x01 /* default is extend size */

通常情况下,偏移量和长度要求是文件系统的block size大小,否则fallocate调用可能失败并返回EINVAL。

除了上面这两个flag外,还有另外一个比较有意思的flag:FALLOC_FL_COLLAPSE_RANGE,名字和其功能比较形象,相当于在挖洞后,这个洞并没有留下,而是把后面的数据往前面移,因此被打洞的部分,在被随后访问到时,读取到的数据就不是0,而是后面的数据。

关于这个flag可以参考这篇文章了解其背景。

文件的管理使用sparse file(稀疏文件),一般支持punch hole特性的,都会支持sparse file,对于sparse file,可以参阅这篇博客,讲的非常详细。简单的重整了下博客中的配图,如下所示:

sparse file

然而需要注意一种情况,由于文件中的空洞不占磁盘空间,当磁盘接近满时,如果向空洞写入数据,就可能触发写入失败的问题,导致不可预料的问题,因此空余的磁盘空间阀值需要多预留点。

InnoDB 新压缩实现

MySQL 5.7.8版本实现了一种新的压缩方式(WL#7696),也就是所谓的Innodb Transaparent PageIO Compression,其原理很简单,就是利用punch hole + 数据压缩来实现的。其在内存中表现的是一个正常的page,只在读写到磁盘时,才进行文件压缩、解压处理。处理逻辑如下图所示:

innodb punch

首先,InnoDB增加了新的Page类型,这意味着如果使用该特性,则不能原地降级到老版本,需要对格式进行转换才能降级。

目前上游支持两种压缩算法:zllib及lz4,但我们也可以很方便的进行扩展新的算法。

被压缩的数据包含除FIL_PAGE_DATA之外的所有数据(包括tailer),但需要以block size对齐(线上环境的block size通常为4KB),这意味着即使我们把数据从16KB压缩到9KB,也需要存储12KB的数据。因此block size设小点,这样的场景将受益,可以减少空间浪费。

表定义

首先需要操作系统支持该特性,在阿里的环境里,需要装上新版内核(如上述)让系统支持punch hole。

可以通过CREATE TABLE 或ALTER TABLE 来定义压缩表:

mysql> create table sb1 (a int, b blob) compression='zlib';
Query OK, 0 rows affected (0.05 sec)

也可以选择compression=’lz4’来指定lz4压缩算法;注意对compression属性的ALTER是立刻生效的,因此在做完ALTER COMPRESSION属性操作后,需要做一次表的rebuild,例如optimize table操作,才能对已有的数据做punch hole。

compression属性存储在frm文件中,以两个字节存储字符串长度,随后存储compression属性定义字符串,这也是一个操作系统降级的风险点。

具体的使用参阅官方文档

相关代码逻辑

压缩数据

压缩数据发生在对磁盘进行IO WRITE之前:

  1. 先在内存中压缩数据,并对齐Block size,确定做punch hole的范围,同时将即将写入文件的buf地址指向新分配的压缩页地址(这里存在优化的空间,需要避免重复分配内存块)。参考函数:
    • Native AIO: AIO::reserve_slot –> os_file_compress_page
    • 同步写:os_file_pwrite –> os_file_io –> os_file_compress_page
  2. 将压缩处理过的page写入文件;
  3. 随后调用函数os_file_io_complete中,执行punch hole操作(os_file_punch_hole)。

解压数据

在从磁盘读取数据到磁盘后,首先要进行解压:参考函数:os_file_io_complete –> os_file_decompress_page

特殊处理

  1. 通过dblwr恢复的corruption的page写入时禁止压缩模式,因为此时innodb处于恢复模式,还没拿到server层存储的compression属性;
  2. row_merge_read 和row_merge_write,一般是用于排序的临时文件,无需做压缩/解压;
  3. truncate操作的文件日志禁止压缩模式。

代码整体的逻辑比较清晰,但改动点还比较多,后续我们将该特性Port到RDS版本,结合新内核来发挥数据空间节省的目的。

最后,Facebook的大神Domas写了一篇博客,认为InnoDB推出这样的压缩特性,使其正在丧失自身的优势,非常值得一读。简单的摘要下:

  • 无法完美压缩:例如9KB的数据可能需要12kb来存储,取决于block size;
  • 无法压缩Buffer pool, 这是和传统innodb压缩相比,以前的压缩方式可以在内存中只存放压缩页拷贝 (然而也有可能同时存在压缩和解压页),因此用户可能需要去购买iops更高的设备,而oracle正好也卖这些….
  • punch hole 可能产生的文件碎片化,底层的文件管理更加复杂;
  • 对innodb文件做punch hole可能带来的后果是,使得每个文件的page变成一个独立的segment,文件系统需要单独的journal和metadata来管理。另外也有可能有性能问题:可能比non-sparse的写操作昂贵五倍 (这依赖于具体的内核);
  • 删除一个拥有几百万个段管理对象的数据文件带来的开销会非常昂贵。
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
10月前
|
存储 网络协议 关系型数据库
MySQL8.4创建keyring给InnoDB表进行静态数据加密
MySQL8.4创建keyring给InnoDB表进行静态数据加密
389 1
|
5月前
|
存储 关系型数据库 MySQL
介绍MySQL的InnoDB引擎特性
总结而言 , Inno DB 引搞 是 MySQL 中 高 性 能 , 高 可靠 的 存 储选项 , 宽泛 应用于要求强 复杂交易处理场景 。
223 15
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
2154 57
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
11月前
|
前端开发 Java 关系型数据库
基于ssm的社区物业管理系统,附源码+数据库+论文+任务书
社区物业管理系统采用B/S架构,基于Java语言开发,使用MySQL数据库。系统涵盖个人中心、用户管理、楼盘管理、收费管理、停车登记、报修与投诉管理等功能模块,方便管理员及用户操作。前端采用Vue、HTML、JavaScript等技术,后端使用SSM框架。系统支持远程安装调试,确保顺利运行。提供演示视频和详细文档截图,帮助用户快速上手。
472 17
|
10月前
|
SQL 缓存 关系型数据库
使用温InnoDB缓冲池启动MySQL测试
使用温InnoDB缓冲池启动MySQL测试
193 0
|
12月前
|
关系型数据库 分布式数据库 数据库
喜报|PolarDB开源社区荣获“2024数据库国内活跃开源项目”奖
喜报|PolarDB开源社区荣获“2024数据库国内活跃开源项目”奖
261 1
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
634 7
|
存储 关系型数据库 MySQL
Mysql索引:深入理解InnoDb聚集索引与MyisAm非聚集索引
通过本文的介绍,希望您能深入理解InnoDB聚集索引与MyISAM非聚集索引的概念、结构和应用场景,从而在实际工作中灵活运用这些知识,优化数据库性能。
652 7
|
存储 关系型数据库 MySQL
MySQL引擎InnoDB和MyISAM的区别?
InnoDB是MySQL默认的事务型存储引擎,支持事务、行级锁、MVCC、在线热备份等特性,主索引为聚簇索引,适用于高并发、高可靠性的场景。MyISAM设计简单,支持压缩表、空间索引,但不支持事务和行级锁,适合读多写少、不要求事务的场景。
279 9
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
406 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件

相关产品

  • 云数据库 RDS MySQL 版