InnoDB的主要的磁盘文件主要分为三大块:一是系统表空间,二是用户表空间,三是redo日志文件和归档文件。
重做日志文件
默认情况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件,这就是InnoDB的重做日志文件(redo log file),它记录了对于InnoDB存储引擎的事务日志。
重做日志文件的作用是什么?
- 当InnoDB的数据存储文件发生错误时,重做日志文件就能派上用场。InnoDB存储引擎可以使用重做日志文件将数据恢复为正确状态,以此来保证数据的正确性和完整性。
- 为了得到更高的可靠性,用户可以设置多个镜像日志组,将不同的文件组放在不同的磁盘上,以此来提高重做日志的高可用性。
重做日志文件组是如何写入数据的?
每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组下至少有2个重做日志文件,如默认的ib_logfile0和ib_logfile1。
- 在日志组中每个重做日志文件的大小一致,并以循环写入的方式运行。
- InnoDB存储引擎先写入重做日志文件1,当文件被写满时,会切换到重做日志文件2,再当重做日志文件2也被写满时,再切换到重做日志文件1。
如何设置重做日志大小
用户可以使用innodb_log_file_size来设置重做日志文件的大小,这对InnoDB存储引擎的性能有着非常大的影响。
- 大小设置的太大,数据丢失时,恢复时间长
- 设置的太小时,会导致依据checkPoint检查机制频繁刷新脏页到磁盘中导致性能抖动
详细可参考 如何设置innodb_log_file_size
系统表空间
系统表空间是一个共享的表空间,因为它是被多个表共享的。
- 系统表空间是由一个或者多个数据文件组成。
- 默认情况下,一个初始大小为10MB,名为ibdata1的系统数据文件在MySQL的data目录下被创
建。用户可以使用 innodb_data_file_path 对数据文件的大小和数量进行配置。
系统表空间存储哪些数据?
- InnoDB系统表空间包含InnoDB数据字典(元数据以及相关对象)、double write buffer(脏页落盘时使用的双写缓冲区)、change buffer(修改缓冲区)、undo logs的存储区域。
- 系统表空间也默认包含任何用户在系统表空间创建的表数据和索引数据。
用户表空间
- 如果设置了参数innodb_file_per_table,则用户可以将每个基于InnoDB存储引擎的表产生一个独立的用户表空间。用户表空间的命名规则为:表名.ibd。
- 通过这种方式,用户不用将所有数据都存放于默认的系统表空间中。
用户表空间存储哪些数据?
用户表空间只存储该表的数据、索引信息,其余信息还是存放在默认的系统表空间中。
InnoDB逻辑存储结构
InnoDB存储引擎逻辑存储结构可分为五级:表空间、段、区、页、行。
表空间
- 从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace)。
- 从功能上来看,InnoDB存储引擎的表空间分为系统表空间,独占表空间(通常叫用户表空间),通用表空间,临时表空间,Undo表空间。
- 如果开启了独立表空间innodb_file_per_table=1,每张表的数据都会存储到一个独立的表空间,即一个单独的.ibd文件。
- InnoDB 存储引擎有一个共享表空间,叫做系统表空间,对一个磁盘上的文件名为ibdata1。如果设置了参数innodb_file_per_table=0,关闭了独占表空间,则所有基于InnoDB存储引擎的表数据都会记录到系统表空间。
段
- 无论是系统表空间还是用户表空间都是由各个段组成的,常见的段有数据段、索引段、回滚段等。
- 数据段存储着索引树中叶子节点数据。
- 索引段存储这索引树种非叶子结点的数据。
- 段的大小会随着表的大小自动扩大(表有多大,段就有多大)。
- 一个段会包含多个区,至少会有一个区,段扩展的最小单位是区。
区
一个区由64个连续的页组成,一个区的大小=1M=64个页(16K)。为了保证区中页的连续性,区扩展时,InnoDB 存储引擎会一次性从磁盘申请4 ~ 5个区。
页
InnoDB 每个页默认大小时是 16KB,页是 InnoDB管理磁盘的最小单位,也InnoDB中磁盘和内存交互的最小单位。
show global variables like 'innodb_page_size';
索引树上一个节点就是一个页,MySQL规定一个页上最少存储2个数据项(行)。如果向一个页插入数据时,这个页已将满了,就会从区中分配一个新页。
如果这个页已经有2行数据,需要在里面更新数据或者插入数据(id=1,3中间插入id=2的数据)时,如果空间不够用(更新或插入后的总数据大小超过了16K)就会发生页分裂。详情可参考:页内数据超出16K怎么办
操作系统管理磁盘的最小单位也是页,是操作系统读写磁盘最小单位,Linux中页一般是4K,可以通过命令查看。
# 默认 4096 4K
getconf PAGE_SIZE
所以InnoDB从磁盘中读取一个数据页时,操作系统会分4次从磁盘文件中读取数据到内存。写入也是
一样的,需要分4次从内存写入到磁盘中。
行
InnoDB的数据是以行为单位存储的,1个页中包含多个行(行数根据每行数据大小决定)。在MySQL5.7中,InnoDB提供了4种行格式:Compact、Redundant、Dynamic和Compressed行格式,Dynamic为MySQL5.7默认的行格式。