InnoDB 把数据保存在表空间内,本质上是一个由一个或多个磁盘文件组成的虚拟文件系统。InnoDB用表空间并不只是存储表 和索引 ,还保存了回滚段 、双写缓冲区 等。本文将介绍InnoDB表空间的相关性质。
调整InnoDB系统表空间大小
增加InnoDB系统表空间大小
增加InnoDB系统表空间大小的最简单方法就是初始化配置为自动扩展(autoextend) 。 在表空间定义中为最后一个数据文件指定autoextend 属性,这样InnoDB在空间不足时以64MB的增量自动增加该文件的大小。 可以通过设置innodb_autoextend_increment 系统变量的值来更改增量大小(单位为MB)。为了扩展系统表空间,开发人员可通过添加新的数据文件:
关闭数据库;
若之前使用了autoextend ,可以将其替换为明确的数据文件名及文件大小,如:
innodb_data_home_dir =
# before
innodb_data_file_path = / ibdata / ibdata1 : 988 M : autoextend
# after
innodb_data_file_path = / ibdata / ibdata1 : 988 M ; / disk2 / ibdata2 : 50 M : autoextend
启动数据库。
减小InnoDB系统表空间大小
在InnoDB 中,开发人员并不能直接从系统表空间 中删除数据文件,为了减小系统表空间,可以执行如下操作:
关闭数据库;
删除所有表空间文件(*.ibd 文件),包括ibdata 和ib_log 等文件,再删除所有InnoDB表文件(*.frm 文件);
配置新的表空间,启动数据库,再导入之前dump的文件。
改变重建日志文件(Redo Log)的数量及大小
若开发人员想改变InnoDB重建日志文件 的数量及大小,可以执行如下操作:
正常关闭数据库;
修改
my.cnf 文件,配置
innodb_log_files_in_group (修改文件数量,文件名通常为ib_logfile0, ib_logfile1, ib_logifleN)和
(文件大小,若之前有日志文件大小不一致,会先写
Checkpoint ,再创建新的日志文件);
启动数据库。
使用裸磁盘分区
开发人员可以在InnoDB系统表空间 中使用裸磁盘分区 作为数据文件。 此技术在Windows和某些Linux和Unix系统上会启用无缓冲I/O ,这样无需文件系统开销,然而最终是否使用裸磁盘分区,还是应该进行测试,以验证此更改是否真实提高了系统性能。对于Linux或Unix系统,可按如下操作执行:
确保启动MySQL服务器 的用户对裸磁盘分区具有读写权限 ;
创建新数据文件时,须在innodb_data_file_path 选项的数据文件大小后指定关键字newraw , 分区必须至少比指定的大小大。注意,InnoDB中的1MB是1024×1024字节,而磁盘规格中的1MB通常意味着1,000,000字节:
[ mysqld ]
innodb_data_home_dir =
innodb_data_file_path =/ dev / hdd1 : 3 Gnewraw ; / dev / hdd2 : 2 Gnewraw
重新启动服务器。InnoDB会根据newraw 关键字并初始化新分区。然而,此时不应该创建或更改任何InnoDB表,否则,当下次重新启动服务器时,InnoDB将重新初始化分区,之前的更改将丢失(因此,为了安全起见,InnoDB会组织用户修改newraw 分区);
当InnoDB 初始化分区后,则关闭数据库,并修改newraw 关键字为raw :
[ mysqld ]
innodb_data_home_dir =
innodb_data_file_path =/ dev / hdd1: 3 Graw ;/ dev / hdd2: 2 Graw
重启数据库,此时便可以进行修改操作。
Innodb File-Per-Table 表空间
过去,所有InnoDB 表和索引都存储在系统表空间 中,这种整体方法针对的是完全专用于数据库处理的机器,并且经过精心规划的数据增长 ,分配给MySQL的任何磁盘存储都不需要用于其他目的。现在InnoDB针对每个表的表空间提供了一个更灵活的选择,将每个InnoDB表及其索引存储在单独的.ibd 数据文件中,每个这样的.ibd数据文件都表示一个单独的表空间。此功能可由innodb_file_per_table 配置选项控制,默认情况下,此选项在MySQL 5.6.6及更高版本中启用。innodb_file_per_table 带来了诸多好处,但也会有一些缺点,下面将分别讲述。
File-Per-Table表空间的优势
当截取(
TRUNCATE )或删除(
DROP )表可以回收对应的磁盘空间。相对于截取或删除存储在
系统表空间 中的表,其空间只能被InnoDB使用,而不能由操作系统使用。类似地,对驻留在
系统表空间 中的表执行表复制
ALTER TABLE 操作可以增加表空间使用的空间量。这样的操作可能需要与表中的数据和索引一样多的额外空间。表复制ALTER TABLE操作所需的额外空间不会释放回操作系统,因为它是针对单个表的文件表空间;
为了
提升I/O性能 ,
空间管理 或者
备份 ,用户可以将指定表存储在
单独的存储设备 上。 在以前的版本中,必须将
整个数据库目录 移动到其他驱动器,并在MySQL数据目录中创建
符号链接 。在MySQL 5.6.6之后,可以使用语法
CREATE TABLE ... DATA DIRECTORY = absolute_path_to_directory 指定每个表的位置,即
为每个表空间创建外部数据目录 ;
用户可以执行
OPTIMIZE TABLE 来
压缩 或
重新创建 每个表的文件表空间。当运行
OPTIMIZE TABLE 时,InnoDB将使用临时名称创建一个新的
.ibd 文件,这会使用存储实际数据所需的空间。 当优化完成后,InnoDB将删除旧的.ibd文件,并用新的.ibd文件替换它。如果旧的.ibd文件显着增长,但实际数据仅占其大小的一部分,则运行
OPTIMIZE TABLE 可以回收未使用的空间;
用户可以移动单个Innodb表而不是整个数据库;
以文件表空间创建的表会使用
Barracuda 文件格式,
Barracuda 文件格式支持
压缩和动态行格式 等特性;
用户可以使用
动态行格式 为
BLOB 或
TEXT 列的表启用更高效的存储;
当发生损坏 ,服务器无法重新启动 ,或者备份和二进制日志不可用 时,File-per-table 表空间可以提升成功恢复的机会 和节省时间 ;
File-per-table 表空间便于在复制 或备份 表时,进行每个表的状态报告;
用户无需访问MySQL,便可以在文件系统级别监控表大小;
当
innodb_flush_method 设置为
O_DIRECT 时,通用Linux文件系统不允许并发写入单个文件。因此,将
file-per-table 表空间与
innodb_flush_method 结合使用,有可能会提高并发写性能。
系统表空间 存储数据字典和撤销日志,并且大小受InnoDB表空间 大小的限制,对于file-per-table 表空间,每个表都有自己的表空间,这就提供了增长空间。
File-Per-Table表空间的潜在缺点
对于file-per-table 表空间,每个表可能都有未使用的空间,并且只能由相同表的行使用,如果未能正确管理,这可能会导致浪费空间;
fsync 操作必须在每个打开的表上运行,而不是在单个文件上运行。 因为每个文件都有单独的fsync操作,因此多个表上的写操作不能合并到单个I/O操作中,这可能需要InnoDB 执行更多的fsync操作;
mysqld 必须为每个表保留一个打开的文件句柄,如果在
file-per-table 表空间中有许多表,这可能会影响性能;
会使用更多的文件描述符;
innodb_file_per_table 默认情况下在
MySQL 5.6.6 及更高版本中启用。如果考虑向后兼容MySQL 5.5或5.1,可以考虑禁用它。在
ALTER TABLE 重新创建表(
ALGORITHM = COPY )的情况下,禁用
innodb_file_per_table 可防止
ALTER TABLE 将InnoDB表从
系统表空间 移动到单个
.ibd 文件;
如果许多表都在增长,则由可能产生更多碎片,这可能阻碍DROP TABLE 和表扫描 性能。 不过,当碎片可控时,在innodb_file_per_table 表空间则可以提高性能;
当删除innodb_file_per_table 表空间时,将扫描缓冲池,对于大小为数十GB的缓冲池,可能需要几秒钟。 使用内部锁执行扫描,则可能会延迟其他操作,而系统表空间中的表不受影响;
innodb_autoextend_increment 变量定义了在自动扩展
共享表空间时,扩展的增量大小(以MB为单位),但不适用于自动扩展的file-per-table 表空间文件,无论innodb_autoextend_increment 是否设置,初始扩展是比较小的,之后扩展则以4MB 的增量大小执行。
启用或禁用File-Per-Table表空间
启用或禁用,只需配置innodb_file_per_table ,如:
[ mysqld ]
innodb_file_per_table = 1
或者运行时修改:
SET GLOBAL innodb_file_per_table = 1;
具体细节可见这里 。
为File-Per-Table创建外部数据目录
为File-Per-Table 创建外部数据目比较简单,只需在创建表时指定外部目录即可,这样InnoDB将在对应目录创建目标数据库目录及表空间文件,如:
CREATE TABLE t1 ( c1 INT PRIMARY KEY ) DATA DIRECTORY = '/path/to/data_dir' ;
复制File-Per-Table表空间到其他数据库实例
将文件每表表空间从一个数据库实例复制到另一个数据库实例,也称为可传输表空间 功能。在MySQL 5.7.4之前,只支持非分区 的InnoDB表。从MySQL 5.7.4开始,还支持分区的InnoDB表和各个InnoDB表分区和子分区。现实中,可能会有不同原因需要作表复制,如:
作数据报表时,为了不影响生产服务器上,需要先复制到临时数据库;
在出现问题或错误后,恢复表或分区的备份版本;
作为一种更快的移动数据的方式,而不是通过
mysqldump 命令倒入,这样数据可以立即可用,不必重新插入并重建索引;
将File-Per-Table 表空间移动到具有更适合系统要求的存储介质的服务器;
...
对于具体如何执行表复制,可参考该文章 。
在单独的表空间中存储撤销日志(Undo Logs)
用户可以将InnoDB撤销日志 (也被称为回滚段 )存储在系统表空间 之外的一个或多个单独的撤销表空间 中。 此设计与默认配置不同,其中撤销日志是系统表空间的一部分。 撤消日志的I/O模式 使得这些表空间迁移到SSD存储 更具优势,同时将系统表空间 保留在硬盘存储 上。 用户不能删除创建的用于单独存储撤销日志的表空间,也不能删除这些表空间中的各个段。但是,从MySQL 5.7.5 开始,存储在撤销表空间 中的撤销日志可以被截取(truncate)。截取撤销日志细节可参考这里 。由于撤销日志 相关特性不能动态配置,因此只能在初始化MySQL实例时启用。
将撤销日志 保存在单独的文件中,这样使得与事务数据相关的I/O和内存操作得到优化。 例如,因为撤销日志 被写入磁盘,但其实很少会读取(仅在崩溃恢复的情况下),它不需要保存在文件系统高速缓存中,从而允许将更多的内存用于InnoDB缓冲区 。
启用撤销日志特性,大致步骤如下,细节可参考这里 :
根据上述配置,创建新的MySQL实例(初始化启动MySQL);
对I/O性能作基准测试;
定期增加innodb_undo_logs 的值并重新作性能测试,找出I/O性能最高时的innodb_undo_logs 值。
截取撤销日志(Truncating Undo Logs)
从MySQL5.7.5后,用户可以通过innodb_undo_log_truncate 配置选项开启截取撤销日志 。当启用innodb_undo_log_truncate 后,超过由innodb_max_undo_log_size 配置定义的阈值的表空间将标记为截断。注意,只有存储在撤销表空间中的撤销日志才能被截取,系统表空间中的撤销日志不支持截断。 要使得截取发生,必须至少有两个撤销表空间 ,且都启用了重坐撤销日志 的配置选项。 这也意味着innodb_undo_tablespaces 必须设置为大于等于2的值,innodb_undo_logs 必须设置为等于或大于35的值。具体细节可参考这里 。
InnoDB通用表空间(General Tablespaces)
通用表空间 是一种新的InnoDB表空间,在MySQL 5.7.6中引入。通用表空间 特性主要有以下功能:
与系统表空间 类似,通用表空间 是可以存储多个表的数据;
通用表空间 相对于
file-per-table 表空间具有潜在的内存优势。服务器在表空间的生命周期内会将表空间元数据保存在内存中,而将多张表的元数据信息保存在
通用表空间 内相对于每张表单独将各自元数据保存在自己的表空间内会更节省内存;
通用表空间 数据文件可以被放置在相对于或独立于MySQL数据目录的目录中,该目录提供了许多对file-per-table 表空间的数据文件和存储管理的功能。与file-per-table 表空间表空间一样,将数据文件放在MySQL数据目录之外,使得可以分别管理关键表的性能,例如为特定表设置RAID 或DRBD ,或将表绑定到特定磁盘;
TABLESPACE 选项可与
CREATE TABLE 一起,在
通用表空间 ,
file-per-table 表空间或
系统表空间 中创建表;
TABLESPACE 选项可与
ALTER TABLE 一起,在
通用表空间 ,
file-per-table 表空间或
系统表空间 之间移动表。以前,不可能将表从
file-per-table 表空间移动到
系统表空间 ,而使用
通用表空间 特性,则可以这么做。
通用表空间具体使用,可参考这里 。
InnoDB表空间加密(Encryption)
InnoDB支持对存储在file-per-table 表空间中的表的数据进行加密,该特性对物理表空间的数据文件提供静态加密 。InnoDB表空间加密使用两层加密密钥体系结构,包括主加密密钥 和表空间密钥 。当InnoDB表被加密时,表空间密钥被加密并存储在表空间头中。 当应用程序或已认证的用户想要访问加密的表空间数据时,InnoDB使用主加密密钥 来解密表空间密钥 。表空间密钥的解密版本从不改变,但是主加密密钥可以根据需要改变,此操作称为主密钥旋转 。上述加密特性需依赖keyring_file 插件,具体加密细节可参考这里 。
总结
以上,则是InnoDB表空间的相关特性,开发人员则可以针对不同业务特性,场景等作一系列相关优化等。
参考文献