上图详细显示了InnoDB存储引擎的体系架构,从图中可见,InnoDB存储引擎由内存结构和磁盘结构两大部分组成。
InnoDB的主要的磁盘文件主要分为三大块:一是表空间,二是双写缓冲区,三是重做日志,数据字典表空间。
1:InnoDB逻辑存储结构
InnoDB存储引擎逻辑存储结构可分为五级:表空间、段、区、页、行。
1.表空间
从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间
(tablespace)。
从功能上来看,InnoDB存储引擎的表空间分为系统表空间,独占表空间,通用表空间,临时表空间,Undo表空间。
如果开启了独立表空间innodb_file_per_table=1,每张表的数据都会存储到一个独立的表空间,即一个单独的.ibd文件。
InnoDB 存储引擎有一个共享表空间,叫做系统表空间,对一个磁盘上的文件名为ibdata1。如果设置了参数innodb_file_per_table=0,关闭了独占表空间,则所有基于InnoDB存储引擎的表数据都会记录到系统表空间。
2.段
表空间是由各个段组成的,常见的段有数据段、索引段、回滚段等。
如果开启了独立表空间innodb_file_per_table=1,每张表的数据都会存储到一个独立的表空间,即一个单独的.ibd文件。一个用户表空间里面由很多个段组成,创建一个索引时会创建两个段:数据段和索引段。
数据段存储着索引树中叶子节点的数据。
索引段存储着索引树中非叶子节点的数据。
一个段会包含多个区,至少会有一个区,段扩展的最小单位是区。
3.区
一个区由64个连续的页组成,一个区的大小=1M=64个页(16K)。为了保证区中页的连续性,区扩展时InnoDB 存储引擎会一次性从磁盘申请4 ~ 5个区。
4.页
InnoDB 每个页默认大小时是 16KB,页是 InnoDB管理磁盘的最小单位,也InnoDB中磁盘和内存交互的最小单位。
show global variables like 'innodb_page_size';
索引树上一个节点就是一个页,MySQL规定一个页上最少存储2个数据项。如果向一个页插入数据时,这个页已将满了,就会从区中分配一个新页。如果向索引树叶子节点中间的一个页中插入数据,如果这个页是满的,就会发生页分裂。
操作系统管理磁盘的最小单位也是页,是操作系统读写磁盘最小单位,Linux中页一般是4K,可以通过命令查看。
#默认 4096 4K
> getconf PAGE_SIZE
所以InnoDB从磁盘中读取一个数据页时,操作系统会分4次从磁盘文件中读取数据到内存。写入也是一样的,需要分4次从内存写入到磁盘中。
5.行
InnoDB的数据是以行为单位存储的,1个页中包含多个行。在MySQL8中,InnoDB提供了4种行格式:Compact、Redundant、Dynamic和Compressed行格式,Dynamic为MySQL8默认的行格式。
InnoDB行格式官网:MySQL :: MySQL 8.0 Reference Manual :: 15.10 InnoDB Row Formats
创建表时可以指定行格式:
CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;
ALTER TABLE tablename ROW_FORMAT=行格式名称;
#修改默认行格式
SET GLOBAL innodb_default_row_format=DYNAMIC;
#查看表行格式
SHOW TABLE STATUS LIKE 'student'\G;
2:MySQL数据字典
在以前的MySQL版本中,字典数据存储在元数据文件,非事务表和存储引擎特定的数据字典中。
MySQL8中包含一个事务数据字典,用于存储有关数据库对象的信息,所有的元数据存储在 MySQL 数据字典中也就是 mysql.ibd 文件中。
数据字典表受到保护,只能在MySQL的调试版本中访问。但是,MySQL支持通过 INFORMATION_SCHEMA 表 和 SHOW语句 访问存储在数据字典表中的数据。
SELECT table_name, table_type, engine FROM information_schema.tables ORDER BY table_name;
MySQL系统表仍然存在于MySQL 8.0中,可以通过在系统数据库上发出SHOW TABLES语句来查看。通常,MySQL数据字典表和系统表之间的区别在于数据字典表包含执行SQL查询所需的元数据,而系统表包含时区和帮助信息等辅助数据。MySQL系统表和数据字典表在升级方式上也有所不同。
3:系统表空间
系统表空间存储哪些数据?
系统表空间是修改缓冲区的存储区域。如果表是在系统表空间中创建的,而不是在按每个表一个文件或在通用表空间中创建的,则它还可能包含表和索引数据。在以前的MySQL版本中,系统表空间包含数据字典。在 MySQL 8.0 中,将元数据存储在 MySQL 数据字典中。在之前的MySQL版本中,系统表空间还包含双写缓冲区存储区域。从MySQL 8.0.20开始,此存储区域驻留在单独的双写文件中。
系统表空间可以有一个或多个数据文件。默认情况下,将在数据目录中创建一个名为 ibdata1 的单个系统表空间数据文件。系统表空间数据文件的大小和数量由 innodb_data_file_path 参数定义。
增加系统表空间大小的最简单方法是将其配置为自动扩展。
innodb_data_file_path=ibdata1:10M:autoextend
示例(这里将/db/ibdata1和/dr2/db/ibdata2两个文件组成系统表空间):
innodb_data_file_path=/db/ibdata1:1000M;/dr2/db/ibdata2:1000M:autoextend
如果这两个文件位于不同的磁盘上,磁盘的负载可能被平均,因此可以提高数据库的整体性能。两个文件的文件名之后都跟了属性,表示文件 ibdata1 的大小为 1000MB ,文件 ibdata2 的大小为 1000MB ,而且用完空间之后可以自动增长 autoextend 。
4:用户表空间
InnoDB默认情况下,对应每个表创建一个独立表空间文件即 .ibd 文件。此行为由
innodb_file_per_table 变量控制。禁用 innodb_file_per_table 导致在系统表空间中创建表。
用户表空间存储哪些数据?
用户表空间存储该表的数据、索引信息、SDI(序列化字典信息)。
1. 独立表空间的优点
在截断或删除在独立表空间中创建的表后,操作系统可以回收磁盘空间。截断或删除存储在共
享表空间中的表会在共享表空间数据文件中会产生碎片空间,这些碎片空间只能用于存储数
SELECT table_name, table_type, engine FROM information_schema.tables ORDER BY table_name; 11 innodb_data_file_path=ibdata1:10M:autoextend 1 innodb_data_file_path=/db/ibdata1:1000M;/dr2/db/ibdata2:1000M:autoextend
据。换言之,共享表空间数据文件在表被截断或删除后不会缩小。
对驻留在共享表空间中的表执行复制 ALTER TABLE 操作可能会增加表空间占用的磁盘空间
量。此类操作可能需要与表中的数据加索引一样多的额外空间,而且空间不会释放。
独立表空间中的表执行 TRUNCATE TABLE 操作性能更好。
可以在单独的存储设备上创建每表文件表空间数据文件,以实现 I/O 优化、空间管理或备份目
的。
可以从另一个 MySQL 实例导入独立表空间中的表。
存储在独立表空间的表可以节省数据恢复时间,并提高成功恢复的可能性。
在独立表空间中的表可以快速备份或还原,而不会中断其他表的使用。
独立表空间可以通过监视文件的大小来监视文件系统上的表大小。
共享表空间中的表的大小受 64TB 表空间大小限制的限制。相比之下,每个表文件的表空间的
大小限制为 64TB,这为单个表的大小增长提供了足够的空间。
2. 独立表空间的缺点
对于独立表空间,每个表可能都有未使用的空间,这些空间只能由同一表的行使用,如果管理
不当,可能会导致空间浪费。
fsync对多个每个表的文件数据文件执行操作,而不是对单个共享表空间数据文件执行。由于
操作是按文件执行的,因此不能同时执行多个表的写入操作,这可能会导致操作总数增加。
mysqld必须为每个每个表的文件空间保留一个打开的文件句柄,如果每个表的文件表空间中
有许多表,这可能会影响性能。
当每个表都有自己的数据文件时,需要更多的文件描述符。
可能会出现更多碎片,这可能会妨碍DROP TABLE和表扫描性能。但是,如果管理碎片,则独
立表空间可以提高这些操作的性能。
删除独立表空间的表时,将扫描缓冲池,对于大型缓冲池,这可能需要几秒钟的时间。扫描是
使用全局锁进行锁定,这可能会阻塞其他操作。
5:通用表空间
通用表空间是使用 CREATE TABLESPACE 语句创建的共享表空间。
通用表空间提供以下功能:
与系统表空间类似,通用表空间是能够存储多个表的数据的共享表空间。
与独立表空间相比,通用表空间具有潜在的内存优势。服务器在表空间的生存期内将表空间元数据保留在内存中,与独立表空间中的相同数量的表相比,通用表空间元数据占用的内存更少。
通用表空间数据文件可以放在相对于MySQL数据目录或独立于MySQL数据目录的目录中。与独立表空间一样,将数据文件放置在MySQL数据目录之外或将放到不同的磁盘中。
通用表空间支持所有表行格式和关联的功能。
创建通用表空间:
CREATE TABLESPACE tablespace_name
[ADD DATAFILE 'file_name']
[FILE_BLOCK_SIZE = value]
[ENGINE [=] engine_name]
使用通用表:
-- 建表
CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
-- 修改表
ALTER TABLE t2 TABLESPACE ts1;
6:回滚表空间
在之前的MySQL版本中回滚表空间默认是包含在系统表空间中的,从MySQL8之后默认将回滚表空间独立出来。初始化 MySQL 实例时会创建两个默认回滚表空间文件 undo_001 和 undo_002 。默认回滚表空间是在初始化数据库时创建的,以便为回滚段提供一个位置,回滚段必须先存在,然后才能接受 SQL 语句。
7:临时表空间
InnoDB 使用会话临时表空间和全局临时表空间。
1. 会话临时表空间(#innodb_temp/*.ibt)
会话临时表空间在第一次建立连接时创建两个临时表空间,表空间从临时表空间池中分配。一个用于用户创建的临时表,另一个用于优化程序创建的内部临时表。分配给会话的临时表空间用于该会话创建的所有磁盘临时表。当会话断开连接时,其临时表空间将被截断并释放回池中。
2. 全局临时表空间(ibtmp1)
全局临时表空间在正常关闭或初始化中止时删除,并在每次启动服务器时重新创建。全局临时表空间在创建时会动态生成空间 ID。如果无法创建全局临时表空间,则拒绝启动。如果服务器意外停止,则不会删除全局临时表空间。在这种情况下,数据库管理员可以手动删除全局临时表空间然后重新启动 MySQL 服务器。
8:双写缓冲区
在MySQL早期版本中双写缓冲区存在于系统表空间中,在MySQL8中双写缓冲区独立于系统表空间存在,在磁盘上由两个文件来实现 #ib_16384_0.dblwr 和 #ib_16384_1.dblwr 。是一个存储区域,在内存数据落盘过程中使用该区域。内存页落盘时,先从内存中写入双写缓冲区域,然后再将页写入数据文件中的正确位置。如果存在操作系统、存储子系统,或者在页面写入过程中意外,则可以在崩溃恢复期间从双写缓冲区中找到该页面的正确副本。
9:ib_buffer_pool
重新启动繁忙的服务器后,通常会有一个预热期,吞吐量会稳步增加,因为缓冲池中的磁盘页会被带回内存中(因为查询、更新相同的数据等)。在启动时还原缓冲池的功能通过重新加载重新启动前缓冲池中的磁盘页而不是等待 DML 操作访问相应的行来缩短预热期。此外,I/O 请求可以大批量执行,从而使整体 I/O 更快。页面加载在后台进行,并且不会延迟数据库启动。
这时就需要将innodb buffer pool存储到存储中,在数据文件中进行备份,在重启时innodb 直接读取此文件,但是要保证innodb版本 page页大小,buffer pool大小前后一致。
innodb_buffer_dump_at_shutdown:默认为关闭OFF。如果开启该参数,停止MySQL服务时,InnoDB将InnoDB缓冲池中的热数据保存到本地硬盘。
innodb_buffer_pool_load_at_startup:默认为关闭OFF。如果开启该参数,启动MySQL服务时,MySQL将本地热数据加载到InnoDB缓冲池中。
innodb_buffer_pool_load_now:默认为关闭OFF。如果开启该参数,停止MySQL服务时,以手动方式将InnoDB缓存池中的热数据保存到本地硬盘。
innodb_buffer_pool_filename:如果开启InnoDB预热功能,停止MySQL服务时,MySQL将InnoDB缓冲池中的热数据保存到数据库根目录中,默认文件名为ib_buffer_pool.
innodb_buffer_pool_load_aborr:默认为关闭OFF。如果开启该参数,即便开启InnoDB预热功能,启动MySQL服务室,MySQL也不会将本地硬盘的热数据加载到InnoDB缓冲池中。
10:重做日志文件
默认情况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件,这就是InnoDB的重做日志文件(redo log file),它记录了对于InnoDB存储引擎的事务日志。
1.重做日志文件的作用是什么?
当InnoDB的数据存储文件发生错误时,重做日志文件就能派上用场。InnoDB存储引擎可以使用重做日志文件将数据恢复为正确状态,以此来保证数据的正确性和完整性。
为了得到更高的可靠性,用户可以设置多个镜像日志组,将不同的文件组放在不同的磁盘上,以此来提高重做日志的高可用性。
2.重做日志文件组是如何写入数据的?
每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组下至少有2个重做日志文件,如默认的ib_logfile0和ib_logfile1。
在日志组中每个重做日志文件的大小一致,并以循环写入的方式运行。
InnoDB存储引擎先写入重做日志文件1,当文件被写满时,会切换到重做日志文件2,再当重做日志文件2也被写满时,再切换到重做日志文件1。
3.如何设置重做日志文件大小?
用户可以使用innodb_log_file_size来设置重做日志文件的大小,这对InnoDB存储引擎的性能有着非常大的影响。
如果重做日志文件设置的太大,数据丢失时,恢复时可能需要很长的时间;
另一方面,如果设置的太小,重做日志文件太小会导致依据checkpoint的检查需要频繁刷新脏页到磁盘中,导致性能的抖动。
如果您觉得文章好看,欢迎点赞收藏加关注,一连三击呀,您的肯定是我持续输出的动力,感谢!!☺☻