title: 21-4-27_innodb内幕
date: 2021-04-26 18:34:00
3.6 InnoDB存储引擎文件
3.6.1 表空间文件
默认配置有一个初始12MB,名为ibdata1文件
innodb_data_file_path
可配置
mysql> show variables like ‘innodb_data_file_path‘;
+-----------------------+------------------------+
| Variable_name | Value |
+-----------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
+-----------------------+------------------------+
1 row in set, 1 warning (0.00 sec)
可设置一个或多个文件组成表空间,也可以制定文件属性
若设置为两个文件且位于不同磁盘,则磁盘的负载均衡可能被平均,提高性能,该文件可以自动增长autoextend
设置参数后基于innodb的表数据都会记录到该空间
可设置innodb_file_per_table
,每一个表产生一个独立表空间,表名.ibd
设置了表空间仅存储该表的数据、索引和插入缓冲BITMAP等信息,其余还是存放在默认的表空间
3.6.2 redo日志文件
数据目录下有两个ib_logfile0
和ib_logfile1
文件,即redo日志文件
可以设置多个镜像日志组,将不同文件组放在不同磁盘来提高可用性
大小一致,循环写入
- innodb_log_file_size:每个redo日志大小,最大512GB
- innodb_log_files_in_group:日志组中日志数量,默认2
- innodb_mirrored_log_groups:镜像日志组数量,默认1(在8.0.19中找不到次变量)
- innodb_log_group_home_dir:所在路径
redo日志文件大小需要适当,太大则在恢复时需要很长时间,太小则会导致一个事务的日志需要多次切换redo日志文件,且会导致频繁地发生async checkpoint,造成性能抖动
async checkpoint:redo日志不可用的情况,需要强制将一些页刷新回磁盘
redo日志与bin日志(二进制文件)区别
- bin日志记录所有与MySQL数据库有关的日志,包括所有引擎的日志,redo日志只记录innodb本身的事务日志
- 内容:bin日志记录关于事务的具体操作内容,是逻辑日志,redo日志记录每个page的更改的的物理情况
- 时间:bin日志在事务提交前写入,且仅写入磁盘一次,不论事务多大,redo日志是在事务进行中,不断被写入redo文件
redo日志条目结构
0 | 1 | 2 | 3 |
---|---|---|---|
redo_log_type | space | page_no | redo_log_body |
-
0:占用1字节,类型
-
1:表空间ID,采用压缩方式使占用空间小于4字节
-
2:页的偏移量,压缩
-
3:数据,恢复时需要相应函数进行解析
redo日志写入过程:
先写入redo日志缓冲区,再按顺序写入日志文件
往磁盘写入时,按512字节一个扇区写入(扇区是写入的最小单位),写入必定成功,不需要doublewrite
按条件进行的:
-
master thread每秒写入
-
innodb_flush_log_at_trx_commit:提交事务时处理redo日志的方式
- 0:提交时不写入,等待主线程刷新
- 1:同步
- 2:异步
建议是设为
1
,0或2都可能丢失,2在数据库宕机但操作系统正常时能保证数据不丢失
第4章 表
4.1 索引组织表
根据主键顺序组织存放的存储方式的表称索引组织表
innodb中每张表都有主键,如果没有显示地创建,则会
- 判断是否有非空唯一索引,有则成为主键
- 没有则自动创建字节的RowID指针
_rowid
可以查看单个列为主键的情况(需要有主键)
4.2 InnoDB逻辑存储结构
所有数据都被逻辑存放在表空间(tablespace),表空间又由段(segment)、区(extent)、页(page)组成
4.2.1 表空间
位于逻辑结构的最高层
共享表空间ibdata1
设置参数innodb_file_per_table
则可以单独放到表空间
- 单独表空间存放数据、索引、插入缓冲Bitmap
- 回滚信息,插入缓冲索引页、事务,二次写缓冲等存放在共享表空间
4.2.2 段
表空间由各个段组成,常见的有数据段,索引段,回滚段等
innodb索引即数据,数据即索引,数据段是B+树的叶子节点,索引段即为B+树的非索引节点
4.2.3 区
区由连续64个页组成的,16KB * 64 = 1024KB = 1MB
(任何情况下都是,包括压缩页),为了保证区的连续性,innodb一次从磁盘申请4 ~ 5个区
引入压缩页,大小可以由key block size设置为
2KB, 8KB, 16KB,则对应的页数量 1MB / 2KB = 512, 256, 128
段开始时先用32个页的碎片页来存放数据,使用这些页才是64个连续页的申请,对于小表,节省磁盘开销
4.2.4 页
页是磁盘管理的最小单位,默认16KB,通过innodb_page_size
来设置为4K,8K,16K,设置完成后所有页大小都为此参数的值,不可以再次修改,需要通过mysqldump等其他操作方法
常见页类型:
- 数据页 B-tree Node
- undo页 undo Log Page
- 系统页 System Page
- 事务数据页 Transaction system Page
- 插入缓冲位图页 Insert Buffer Bitmap
- 插入缓冲空闲列表页 Insert Buffer Free List
- 未压缩的二进制大对象页 Uncompressed BLOB Page
4.2.5 行
数据是行存放的,一个页最多存放16KB / 2 - 200行记录,即7992行,最少存放两条记录
4.3 InnoDB行记录格式
mysql 5.7之后默认格式是Dynamic
主要有compact,redundant,dynamic,compressed
4.3.1 Compact行记录格式
首部是非NULL变长字段长度列表,逆序放置,长度为:
- 该列小于255字节,用1字节表示
- 大于,2字节
变长字段长度最大无法超过2字节,如varchar变长字段最大长度限制为65535
第二部分是NULL标志位,有则1表示
第三部分是记录头,固定5字节
最后部分是每个列的实际数据,NULL不占任何空间(除标志位),每行数据还有三个隐藏列,一个事务ID列6字节,回滚指针列7字节, 如果表没有主键,还有一个6字节的rowid列
4.3.2 Redundant
第一个是字段长度偏移列表,逆序,数据小于255字节使用1字节表示,大于255字节使用2字节表示
第二个是记录头信息,6字节,
n_fields
10bit,1111 1111 11
= 1023,则一行记录中列数量最多1023
1byte_offs_flags
代表首部偏移列表长度是1字节还是2字节
最后则是真实数据
4.3.3 行溢出数据
innodb将一条记录中的某些数据存储在真正数据页面之外,如BLOB、LOB这些大对象列数据,VARACHAR也有可能被存放为行溢出数据
varchar(N)中的N指字符的长度,而varchar类型最大支持65535字节,且是所有varchar列的长度总和
一般情况,innodb的数据都在B-tree node中,发生行溢出时,数据存放在页类型为uncompress BLOB页中