存储引擎是MySQL数据库中的核心组件,它决定了数据的存储方式、检索效率以及与其他数据库功能的交互方式
在众多存储引擎中,InnoDB以其事务安全、行级锁定和外键约束等高级功能,成为了MySQL的默认存储引擎
本文将深入探讨MySQL表存储引擎的原理,特别是InnoDB存储引擎的详细实现机制
一、MySQL存储引擎概述 MySQL支持多种存储引擎,每种存储引擎都有其独特的设计目标和应用场景
常见的MySQL存储引擎包括InnoDB、MyISAM、Memory、Federated等
这些存储引擎在数据存储、检索性能、事务支持、并发控制等方面各有千秋
-InnoDB:作为MySQL的默认存储引擎,InnoDB提供了事务安全(ACID兼容)、行级锁定和外键约束等高级功能
它适用于需要事务支持、高并发读写和数据完整性要求较高的场景
-MyISAM:MyISAM是MySQL早期版本的默认存储引擎,它提供了全文索引和压缩功能
MyISAM的读取性能较好,特别是进行全文搜索时,但它不支持事务和行级锁定,因此数据完整性和并发性能较差
-Memory:Memory存储引擎将数据存储在内存中,具有极快的访问速度
它适用于临时表、缓存数据和需要快速响应的场景
然而,由于数据存储在内存中,Memory存储引擎的数据在MySQL服务器重启后会丢失,且表大小受限于可用内存
-Federated:Federated存储引擎允许MySQL服务器访问并操作远程MySQL服务器上的数据,而无需将数据复制到本地服务器
它适用于分布式应用程序和分布式数据库环境
二、InnoDB存储引擎原理 InnoDB是MySQL中最常用的存储引擎之一,其强大的功能和广泛的应用场景得益于其复杂的实现机制
InnoDB存储引擎的原理涉及逻辑存储结构、内存结构、磁盘结构以及事务原理等多个方面
1.逻辑存储结构 InnoDB的逻辑存储结构从高到低依次为表空间、段、区、页和行
-表空间:表空间是InnoDB存储引擎逻辑结构的最高层
如果用户启用了参数`innodb_file_per_table`(在8.0版本中默认开启),则每张表都会有一个表空间(xxx.ibd)
一个MySQL实例可以对应多个表空间,用于存储记录、索引等数据
-段:段分为数据段(Leaf node segment)、索引段(Non-leaf node segment)和回滚段(Rollback segment)
InnoDB是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子节点
段用来管理多个区
-区:区是表空间的单元结构,每个区的大小为1M
默认情况下,InnoDB存储引擎页大小为16K,即一个区中一共有64个连续的页
-页:页是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB
InnoDB存储引擎每次从磁盘申请4-5个区,以保证页的连续性
-行:InnoDB存储引擎数据是按行进行存放的
在行中,默认有两个隐藏字段:`trx_id`(每次对某条记录进行改动时,都会把对应的事务id赋值给`trx_id`隐藏列)和`roll_pointer`(每次对某条记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息)
2. 内存结构 InnoDB存储引擎的内存结构主要包括Buffer Pool(缓冲池)、Change Buffer(更改缓冲区)、Adaptive Hash Index(自适应哈希索引)和Log Buffer(日志缓冲区)四大组件
-Buffer Pool(缓冲池):缓冲池是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据
在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度
缓冲池以Page页为单位,底层采用链表数据结构管理Page
Page根据状态可以分为三种类型:free page(空闲page,未被使用)、clean page(被使用page,数据没有被修改过)和dirty page(脏页,被使用page,数据被修改过,页中数据和磁盘的数据产生了不一致)
-Change Buffer(更改缓冲区):更改缓冲区针对非唯一二级索引页
在执行DML语句(增删改)时,如果这些数据Page没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区中
在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中
Change Buffer占用Buffer Pool空间,默认占25%,最大允许占50%,可以根据读写业务量来进行调整
-Adaptive Hash Index(自适应哈希索引):自适应哈希索引用于优化对Buffer Pool数据的查询
InnoDB存储引擎会监控对表上各索引页的查询,如果观察到在特定的条件下hash索引可以提升速度,则建立hash索引,称之为自适应hash索引
自适应哈希索引无需人工干预,是系统根据情况自动完成
-Log Buffer(日志缓冲区):日志缓冲区用来保存要写入到磁盘中的log日志数据(redo log、undo log),默认大小为16MB
日志缓冲区的日志会定期刷新到磁盘中
如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘IO
3.磁盘结构 InnoDB存储引擎的磁盘结构主要包括系统表空间、文件表空间、通用表空间、撤销表空间、临时表空间和双写缓冲区等
-系统表空间:系统表空间是更改缓冲区的存储区域
如果表是在系统表空间而不是每个表文件或通用表空间中创建的,它也可能包含表和索引数据(在MySQL5.x版本中还包含InnoDB数据字典、undolog等)
-文件表空间:如果开启了`innodb_file_per_table`开关,则每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中
也就是说,每创建一张表,都会产生一个表空间文件,前提是开启了`innodb_file_per_table`开关
-通用表空间:需要通过`CREATE TABLESPACE`语法创建通用表空间,在创建表时,可以指定该表空间
-撤销表空间:MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undo log日志
-临时表空间:InnoDB使用会话临时表空间和全局临时表空间,存储用户创建的临时表等数据
-双写缓冲区:InnoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件,便于系统异常时恢复数据
4. 事务原理 InnoDB存储引擎通过事务来确保数据的完整性和一致性,它支持事务的原子性、一致性、隔离性和持久性(ACID属性)
InnoDB的事务原理主要涉及redo log(保证事务的持久性)、undo log(保证事务的原子性)和MVCC(多版本并发控制)等方面
-redo log:重做日志是用来实现事务的持久性
当事务提交时,InnoDB会将重做日志写入到磁盘中,以确保即使数据库发生崩溃,也可以通过重做日志恢复已提交的事务
-undo log:撤销日志是用来保证事务的原子性
当事务回滚时,InnoDB会使用撤销日志将数据恢复到事务开始之前的状态
此外,撤销日志还用于MVCC中的快照读,以提供一致性的视图
-MVCC(多版本并发控制):MVCC允许多个读者和写者并发访问数据,而不会相互干扰
InnoDB通过为每个事务分配一个唯一的事务ID,并在每行记录中保存两个隐藏字段(`trx_id`和`roll_pointer`)来实现MVCC
当事务读取一行记录时,它会根