21-4-28_innodb内幕


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等信息,其余还是存放在默认的表空间

21-4-28_innodb内幕

3.6.2 redo日志文件

数据目录下有两个ib_logfile0ib_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日志写入过程:

21-4-28_innodb内幕

先写入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逻辑存储结构

21-4-28_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行记录格式

21-4-28_innodb内幕

首部是非NULL变长字段长度列表,逆序放置,长度为:

  • 该列小于255字节,用1字节表示
  • 大于,2字节

变长字段长度最大无法超过2字节,如varchar变长字段最大长度限制为65535

第二部分是NULL标志位,有则1表示

第三部分是记录头,固定5字节

21-4-28_innodb内幕

最后部分是每个列的实际数据,NULL不占任何空间(除标志位),每行数据还有三个隐藏列,一个事务ID列6字节,回滚指针列7字节, 如果表没有主键,还有一个6字节的rowid列

4.3.2 Redundant

21-4-28_innodb内幕

第一个是字段长度偏移列表,逆序,数据小于255字节使用1字节表示,大于255字节使用2字节表示

第二个是记录头信息,6字节,

21-4-28_innodb内幕

n_fields10bit,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页中

21-4-28_innodb内幕

上一篇:django之数据库models


下一篇:mysql主从延迟解决方案