共计 4627 个字符,预计需要花费 12 分钟才能阅读完成。
一、innodb 初探:
1、MySQL 日志文件:
①:slow.log 文件会记录慢查询日志,当一条语句执行时间超过在配置参数 long_query_time 中指定的值时,这条语句就会被记录在这个文件中;
②:error.log 文件会记录一些系统启动或运行时的错误或警告信息,通过配置参数 log_error 来设置;
③:general.log 文件会记录所有在数据库上执行的语句,经常用来追踪问题,但会影响一点性能,所以一般不会打开,只有在调试的时候会偶尔开启。(如果在 QPS 很高的情况下,这个文件可能会非常大不太好处理一般不建议打开)
2、MySQL 系统的 datadir 目录下,有一个目录叫 MySQL:
这个目录实际上是 MySQL 数据库的一些系统表,比如权限、用户等,但这些表都是 MyISAM 存储引擎的表;
3、默认的 3 个数据库实例:information_schema performance_schema sys
①:information_schema:
information_schema 数据库是 MySQL 自带的,它是一个信息数据库,其中保存着关于 MySQL 服务器维护的所有其他数据库的信息,如数据库名、数据库表、表列的数据类型及访问权限等;在该数据库中有数个只读表,它们实际上是视图,而不是基本表;
②:performance_schema:
performance_schema 数据库是在 MySQL5.5 新增的,命名为 performance_schema,该数据库它是针对性能的,主要用于收集数据库服务器性能参数。该数据库有如下功能:
提供进程等待的详细信息,包括锁、互斥变量、文件信息;
保存历史事件汇总信息,为判断 MySQL 服务器性能做出详细的依据
添加或删除监控事件点都非常不容易,并可以随意改变 MySQL 服务器的监控周期;
③:sys:
sys 数据库是 MySQL5.7 中首次加入的系统信息库,这个库类似 Oracle 中动态视图,通过这库可以快速的了解系统的元数据信息,并非常方便的让 DBA 发型数据库的很多信息,在解决性能瓶颈、自动化运维方面提供了巨大的帮助。该库在 MySQL5.7 中是默认的,在 5.6 可以手动导入;
注意:这个库是通过视图的形式把 information_schema 和 performance_schema 结合起来的,查询出让人更加容易理解的结果;但是前提是,sys 库本身的信息来源要依赖 information_schema;
4、innoDB 存储引擎包括两个默认的日志文件,
日志文件大小通过参数 innodb_log_file_size 来设置,个数通过参数 innodb_log_files_in_group 来设置。这几个日志文件的大小被设置后在运行过程中是不能被改变的,如果要修改需要关闭数据库然后修改;
– 注意:innodb 存储引擎还有一个小文件,db.opt 这个文件存储的是 MySQL 数据库的一些配置信息,例如编码,排序的信息,如果在创建数据库时指定一些非默认的参数的话就会在这个文件中存储这些信息;
二、innodb 数据字典:
1、在 MySQL 中是看不到数据字典的,原因就是 MySQL 是一个插件式的数据库管理系统,它的结构分两层,分别是 server 层和存储引擎层,这两层需要相互配合才能一起友好的工作,但是作为一个插件式的数据库管理系统,存储引擎层可以有多个存储引擎的插件,但 server 层只有一个;最早的默认存储引擎为 MyISAM, 它是没有数据字典的,关于表结构,它所拥有的只有.frm 文件,所以这导致了 innodb 也必须要有这个文件才能使得 server 层识别并管理它;
2、innodb 有 4 个最基本的系统表,
用来存储用户定义的表、列、索引及索引列等信息,这些表分别为:sys_tables sys_columns sys_indexes sys_fields
①:sys_tables 表:用来存储所有以 innodb 为存储引擎的表,每条记录对应已经定义的一个表;
name:表示一个表名
ID:表的 ID 号
N_COLSL : 表示这个表的列的个数,建表指定的列数(4 个字节)
type:表示这个表的存储类型,包括记录的格式、压缩等信息(4 个字节)
space:表示这个表所在的表空间 ID 号;
(其中,mix_id mix_len cluster_name 这三个位置暂时使用不到)
②:sys_columns:用来存储 innodb 中定义的所有表中所有列的信息,每一列对应这个表中的一条记录;
table_id:表示这个列所属的表的 ID 号;
pos:表示这个列在表中是第几列;
name:表示这个列的列名
mtype:表示这个列的主数据类型;
prtype:表示这个列的一些精确数据类型,它是一个组合值,包括 null 标志,是否有符号数的标志,是否是二进制字符串的标志及表示这个列是真的 varchar;
len:表示这个列的数据长度,但不包括 varchar 类型,因为这个类型在记录里面存储了数据长度
prec:表示这个列数据的精度,但目前好像没有使用;
③:sys_indexes:用来存储 innodb 中所有表的索引信息,每条记录对应一个索引;
table_id:表示这个索引所属的表的 ID 号
ID:表示这个索引的索引 ID 号
name:表示这个索引的索引名;
n_fields:表示这个索引包含的列个数;
type:表示这个索引的类型,包括聚簇索引、唯一索引、等
space:表示这个索引数据所在表空间 ID 号;
page_no:表示这个索引对应的 B + 树的根页面;
④:sys_fields:用来存储所有索引中定义的索引列,每一条记录对应一个索引列
index_id:这个列所在的索引
pos:这个列在某个索引中是第几个索引列;
col_name:这个索引列的列名;
3、字典表加载:
在 innodb 启动的时候,如果是新建数据库,则需要初始化库,所以首先需要做的就是创建字典管理的 B + 树等信息,在这些初始化操作之后,就通过函数 dict_boot 加载常驻内存的四个系统表并读取一些其他信息;
4、rowid 管理:
在 innodb 中,用户表中的记录不一定都会有一个 rowid 列,rowid 只有在一个表没有定义主键时,也就是需要 rowid 作为聚簇索引列的时候才会被分配给这个表。而 rowid 的管理分配,并不是一个表独享一个 ID 空间,而是全局的,所有表都共享这个 ID 号;
三、innodb 数据存储结构
1、表空间文件组成结构
innodb 存储引擎在存储设计上模仿了 Oracle 的存储结构,其数据是按照表空间进行管理的。新建一个数据库时,innodb 存储引擎会初始化一个名为 ibdata1 的表空间文件,默认情况下,这个文件会存储所有表的数据,以及我们所熟知但看不到的系统表 sys_tables、sys_columns、sys_indexes、sys_fields 等。此外,还会存储用来保证数据完整性的回滚段数据,当然这部分数据在新版本的 MySQL 中,已经可以通过参数来设置回滚段的存储位置了;
innodb 存储引擎的设计很灵活,可以通过参数 innodb_file_per_table 来设置,使得每一个表都对应一个自己的独立表空间文件,而不是存储到公共的 ibdata1 文件中。独立的表空间文件之存储对应表的 B + 树数据、索引和插入缓冲等信息,其余信息还是存储在默认表空间中。
这个文件所存储的内容主要就是 B + 树(索引),一个表可以有多个索引,也就是在一个文件中,可以存储多个索引,而如果一个表没有索引的话,用来存储数据的被称为聚簇索引,也就是说这也是一个索引。最终的结论是,ibd 文件存储的就是一个表的所有索引数据;
2、段:
段是表空间文件中的主要组织结构,它是一个逻辑概念,用来管理物理文件,是构成索引、表、回滚段的基本元素。创建一个索引(B+ 树)时会同时创建两个段,分别是内节点段和叶子段,内节点段用来管理(存储)B+ 树非叶子(页面)的数据,叶子段用来管理(存储)B+ 树叶子节点的数据;也就是说,在索引数据量一直增长的过程中,所有新的存储空间的申请,都是从“段”这个概念中申请的。一个索引,包括两个段,那么一个表的段的数目就是索引的个数乘以 2 了。(更形象的解释:ibd 文件,就是由多个段组成的,没有任何其他空间是脱离了段的管理。)
3、簇:
innodb 引入了簇的概念,在代码中被称为 extent;
簇是构成段的基本元素,一个段由若干个簇构成。一个簇是物理上连续分配的一个段空间,每一个段至少会有一个簇,在创建一个段时会创建一个默认的簇。如果存储数据时,一个簇已经不足以放下更多的数据,此时需要从这个段中分配一个新的簇来存放新的数据。一个段所管理的空间大小是无限的,可以一直扩展下去,但是扩展的最小单位就是簇。簇的空间大小是固定的,一般是 64 个页面;(簇是实际的物理存储空间)
4、页面:
“页面”是簇细分之后的产物,它是簇的组成单位,也是段所管理的最小单位、数据文件管理的最小单位,当然也是文件中空间分配的最小单位。
一个簇中可以包括多个页面(默认为 64 个页面,每个页面是 16KB),这个页面数通常被叫做“簇的大小”。这些页面都归这个簇管理,在逻辑上(页面号都是从小到大连续的)及物理上都是连续的。在向表中插入数据时,如果一个页面已经被写完,系统会从当前簇中分配一个新的空闲页面处理使用,如果当前簇中的 64 个页面都被分配完,系统会从当前页面所在段中分配一个新的簇,然后再从这个簇中分配一个新的页面来使用;(更简单的说:表空间文件就是被划分成相等长度的块,每一个块就是一个页面,一个页面默认为 16KB,一个文件中没有任何空间是脱离了段的管理而存在的)
— 注意:没有任何空间不是一页面的形式而存在的。
5、段、簇、页面组织结构:
一个表空间可以有多个文件,每个文件都有各自的编号,创建一个表空间时,至少有一个文件,这个文件被称为“0 号文件”。一个文件是被切割为等长“默认 16KB”的块,这个块通常被称为页面,那么在“0 号文件”的第一个页面(page_no 为 0)中,存储了这个表空间中所有段簇也管理的入口,那么在这��页面存储的数据就是 16KB,但通常会有页面头信息会占用一些空间,真正的管理信息数据是从页面偏移为 fil_page_data(38) 的位置开始的,这个位置存储了表空间的描述信息;
— 注意:
①:表空间控制信息有:满簇链表、半满簇链表、空闲簇链表,而段的 inode 信息中也有这些信息;表空间中的链表管理的是整个表空间中所有的簇,包括满 簇、半满簇及空闲簇,而段的 iNode 信息中管理的是属于自己段中的满簇、半满簇及空闲簇。
②:在 innodb 中,一个簇描述页面要管理 16384 个页面,簇大小默认为(fsp_extent_size)64 个,而簇描述符的大小为 40B,所以一个簇描述页面中可以描述的簇的个数为(univ_page_size- 页面头长度)/40,其中 univ_page_size=16384B 表示页面大小;在一个表空间中,簇描述页面的存储是每隔 16384 个页面就有一个簇描述页面,所以簇描述页面中只需要描述 16384 个页面即可;
③:所谓的 btr,在 innodb 中,表示的就是 B + 树的处理,不管以它为开头的是函数,还是文件,都是相关的处理,是 Btree 的简称;
: