今日目标
理解逻辑存储结构
理解事务原理
理解 redo log
理解 undo log
InnoDB存储引擎是MySQL中最常用的存储引擎之一,它支持高级事务处理和并发控制,以及稳健的性能。本文将深入探讨InnoDB存储引擎的核心概念和工作原理,包括逻辑存储结构、事务原理。
今日内容介绍,预计花费8分钟
1. 逻辑存储结构
InnoDB的逻辑存储结构如下图所示:
- 表空间(TableSpace):表空间是InnoDB存储引擎逻辑结构的最高层,一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。如果用户启用了参数 innodb_file_per_table(在8.0版本中默认开启) ,则每张表都会有一个表空间(xxx.ibd)
- **段(Segment)**:分为数据段(Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollback segment),。段用来管理多个Extent(区)。
- 数据段(Leaf node segment): InnoDB是索引组织表,数据段就是B+树的叶子节点
- 索引段(Non-leaf node segment): 索引段即为B+树的非叶子节点
- 区(Extent):表空间的单元结构,每个区的大小为1M。默认情况下, InnoDB存储引擎页大小为16K, 即一个区中一共有64个连续的页
- 页(Page):页是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16KB。为了保证页的连续性,InnoDB 存储引擎每次从磁盘申请 4-5 个区
- 行(Row) :行是InnoDB 存储引擎数据是按行进行存放的,在行中,默认有两个隐藏字段:
- Trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
- Roll_pointer:每次对某条引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。
如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!
springboot葵花宝典
主要分享JAVA技术,主要包含SpringBoot、SpingCloud、Docker、中间件等技术,以及Github开源项目
175篇原创内容
公众号
2. 事务原理
2.1. 事务介绍
事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
2.1.1. 事务特性
MySQL事务遵循ACID属性,即原子性、一致性、隔离性和持久性。
- 原子性(Atomicity):事务是不可分割的最小操作单元,事务内的所有操作要么全部成功,要么全部失败。如果出现错误,所有更改都会被撤销,数据库保持一致状态。
- 一致性(Consistency):事务执行后,数据库状态必须满足预定义的一致性状态,不会导致矛盾或不一致的数据。
- 隔离性(Isolation):隔离性控制多个事务之间的相互影响。MySQL支持不同的隔离级别,以满足不同应用的需求。
- 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的,即使发生系统故障也不会丢失。
研究事务的原理,就是研究MySQL的InnoDB引擎是如何保证事务的这四大特性
事务四大特性,实际上分为两个部分。
- 原子性、一致性、持久化: 实际上是由InnoDB中的两份日志来保证的,一份是redo log日志,一份是undo log日志。
- 隔离性: 通过数据库的锁,加上MVCC来保证
接下来研究一下redolog,undolog以及MVCC
3. redo log
redo log:记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。
redo log日志文件由两部分组成:
- 重做日志缓冲(redo log buffer):存储在内存
- 重做日志文件(redo logfile): 存储在磁盘中,当事务提交之后会把所有修改信息都存到该日志文件中, 用于在刷新脏页到磁盘,发生错误时, 进行数据恢复使用。
3.1. redo log作用
思考:如果没有redolog,可能会存在什么问题?
InnoDB引擎内存结构中,主要内存区域是缓冲池,在缓冲池中缓存很多数据页。在一个事务中,执行多个增删改的操作时步骤如下,
- InnoDB引擎会先操作缓冲池中的数据
- 如果缓冲区没有对应的数据,会通过后台线程将磁盘中的数据加载出来,存放在缓冲区中
- 然后将缓冲池中的数据修改,修改后的数据页我们称为脏页。而脏页则会在一定的时机,通过后台线程刷新到磁盘中,从而保证缓冲区与磁盘的数据一致。
注意:缓冲区的脏页数据并不是实时刷新的,而是一段时间之后将缓冲区的数据刷新到磁盘中,假如刷新到磁盘的过程出错了,而提示给用户事务提交成功,而数据却没有持久化下来,这就出现问题了,没有保证事务的持久性。
思考:如何解决上述,数据却没有持久化下来,这就出现问题了,没有保证事务的持久性
在InnoDB中提供了一份日志 redo log,接下来我们再来分析一下,通过redolog如何解决这个问题。
有了redo log之后,当对缓冲区的数据进行增删改之后,
- 首先将操作的数据页的变化,记录在redo log buffer中
- 然后在事务提交时,会将redo log buffer中的数据刷新到redo log磁盘文件中。
- 过一段时间后,如果刷新缓冲区的脏页到磁盘时,发生错误,此时就可以借助于redo log进行数据恢复
上述步骤保证了事务的持久性,如果脏页成功刷新到磁盘 或者涉及到的数据已经落盘,此时redo log就没有作用了,就可以删除了,所以存在的两个redolog文件是循环写的。
思考: 为什么每一次提交事务,要刷新redo log 到磁盘中呢,而不是直接将buffer pool中的脏页刷新到磁盘
因为在业务操作中,我们操作数据一般都是随机读写磁盘的,而不是顺序读写磁盘。而redo log往磁盘文件中写入数据,由于是日志文件,所以都是顺序写的。顺序写的效率,要远大于随机写。这种先写日志的方式,称之为 WAL(Write-Ahead Logging)。
4. undo log(回滚日志)
回滚日志:用于记录数据被修改前的信息 , 作用包含两个 : 提供回滚(保证事务的原子性) 和MVCC(多版本并发控制) 。
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
- Undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。
- Undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment回滚段中,内部包含1024个undo log segment。