连接层处理了客户端和服务器之间的通信细节,主要任务为
里面的三个核心组件, 解析器, 优化器, 执行器,负责完成服务层的核心功能, 其中三个核心组件的交互流程大致如下, 解析器将sql语句转换为解析树, 优化器选择最优的执行方案, 执行器根据计划调用存储引擎执行对应操作并返回结果, 有点类似于公司老总负责将公司战略拆分为一个个小目标分发给公司高管, 然后公司高管决策, 已最高效率达到目的,之后再将任务拆分,给我们打工人, 之后打工人来负责执行
注意:不同存储引擎在磁盘文件上的结构均不一致,这里以InnoDB为例
方便大家理解这三个文件的重要性, 我们先来简单看一下一条写入语句的执行流程,后面再做详细解说
Undo Log
日志文件,为了让其可回滚Buffer Pool
中进行逻辑处理和读取写入Redo Log Buffer
,记录的是相关操作语句innodb_flush_log_at_trx_commit
设置,默认为1,代表在事务提交前将Redo Log Buffer
添加到操作系统内存并立刻进行刷盘,0和2策略的一致性不够强BinLog
可提供变更历史查询,数据库备份和恢复,主从复制等功能 ,当执行修改操作(如插入、更新、删除)时,相关的操作语句或事件信息会被记录到BinLog中。数据库事务开启后才会将数据写入undolog, undoLog中记录的数据主要为以下几类
因为mysql中主键是不能被修改的, 实际上是删除再新增
, 更新非主键和其他类型一样都是一条日志信息当开启一段事务还未提交时,事务中的操作可能会出现错误异常,这时候就可以通过undo log将事务中的操作进行回滚(rollback),意思是回到事务开启前那个状态。
例如:开启事务后,对表中某条记录进行修改(将该记录字段值由value1 ——> value2 ——> value3 ),如果从整个修改过程中出现异常,事务就会回滚,字段的值就回到最初的起点(值为value1 )。
这个很好理解,我们只需要在undo log日志中记录事务中的反向操作即可,发生回滚时直接通过undolog中记录的反向操作进行恢复,例如:
undo log保存的是一个版本链(还能用于MVCC, 解决事务隔离性),也就是使用DB_ROLL_PTR这个字段来连接的。多个事务的 undo-log 日志副本 (数据快照),组成了一个 副本链,
value1 ——> value2 ——> value3 的版本链, 如下图:
为了 提升 Undo Log 读写性能, Undo Log 也在内存中进行了缓存,所处的位置在 Buffer Pool 中,如下图所示:
Buffer Pool 中的 Undo Log 页 是 InnoDB 存储引擎中用于缓存 Undo Log 记录的内存区域。
Buffer Pool 是一个重要的内存结构,用于提高数据库的性能,通过在内存中存储频繁访问的数据页和日志记录,减少对磁盘的 I/O 操作。
以下是有关 Buffer Pool 中 Undo Log 页的详细信息:
buffer pool 中有数据页也有 undo 页,基于wal思想,不仅对buffer pool 中数据页修改操作会记录到redo log buffer,对 undo 页修改操作也会记录到 redo log buffer,这样就通过redo log保证了事务持久性。
当事务Commit之后,undo 页本身就没有利用价值了,此时通过后台线程中的Master Thread或Purge Thread进行 undo 页 的回收工作。
Buffer Pool通过缓存热点数据和索引,减少了磁盘I/O操作,大大提高了数据库的性能。 数据的加载和淘汰机制是维护和优化其性能的关键。 当数据库服务器收到一个查询请求时, 如果数据页在BufferPool中, 则直接返回, 不在则从磁盘中查找, 将数据存BufferPoll后返回
其中页被链表进行管理, 缓存页通过LRU链表管理, 空闲页通过free链管理, flush链表管理脏页(内存中的数据被修改过但尚未同步到磁盘上的数据文件中。)
索引页
存储InnoDB表的索引结构
数据页
存储实际数据行
Undo页
Undo页存储了旧版本的数据,用于支持事务的ACID属性中的原子性、隔离性(Isolation)。
redoLog是物理日志, 记录的是"在某个数据页上进行了修改", 上文提到的脏页, 当内存中的数据修改后, 需要写到磁盘中, 而IO线程不是实时将数据刷入磁盘的, 如果发生非正常的DB重启, 导致内存中的数据丢失, 那么导致数据丢失, 而redoLog就是应对这种情况而生的, 当服务器进行DB恢复时, 会根据redoLog中的数据, 重新持久化刷新磁盘文件
值得注意的是,内存到磁盘是随机IO, 而修改记录到redoLog是顺序IO
数据被修改后的值
redo log通过WAL(Write-Ahead Logging)来进行故障恢复(crash-safe),所谓WAL简单来说就是先写日志,后写磁盘
。
当缓存页被修改后(变成脏页),我们就将本次操作写入到redo log buffer中,
当事务Commit时,就先将redo log buffer中记录通过后台线程刷到磁盘中的redoLog(事务提交是redo log默认刷盘时机)
此时脏页还没有刷入磁盘,但是,只要redo log成功刷盘,就可以认为本次的修改操作完成了,
因为就算发生了故障导致脏页数据丢失,也可以通过磁盘redo log恢复,
所以,redo log 和 undo log 配合起来的作用就是:
这个上面有简略提到过, 通过innodb_flush_log_at_trx_commit
控制, 具体策略如下
两个指针, write pos表示最新写入的位置, checkpoint表示要擦除的位置, 数据结构采用循环队列
其中write pos - checkpoint区域表示待写入的部分(下图绿色部分), checkpoint - write pos表示还未刷入磁盘的记录
redo log 满了,在擦除之前,要确保这些要被擦除记录都已经刷到磁盘中了。在擦除旧记录释放新空间期间,不能再接收新的更新请求,此时 MySQL 性能会下降。因此高并发情况下,合理调整 redo log 大小很重要。
位于存储引擎外,为二进制文件, 像redoLog, undoLog等文件都在InnoDB中, 程序猿没法直接使用,当执行错了一些语句没法恢复如初, 因此才有了binLog
binlog以事件形式记录,不仅记录了操作的语句,同时还记录了语句所执行的消耗的时间. 主要的作用为备份恢复和主从复制
类似于redoLog一样, 都是先写到缓存, binLog是写到servic层的bingLogCache, 然后提交的时候,再写道binLog文件中, 并将bingLogCache清空, 其中刷盘频率可以通过sync_binlog 参数来设置, 具体参数如下
实际上是组提交, 也就是批量提交, 但是两阶段提交便于理解, 这里以两阶段为例
prepare 阶段:将 redo log 对应的事务状态设置为 prepare,然后将 redo log 刷新到硬盘;
commit 阶段:将 binlog 刷新到磁盘,接着调用引擎的提交事务接口,将 redo log 状态设置为 commit(将事务设置为 commit 状态后,刷入到磁盘 redo log 文件);
当事务进行Commit操作时,redo log 和 bin log都会被刷盘持久化保存,但是可能会出现以下两种情况:
双1 配置 (重点):
这个两阶段提交机制保证了 binlog 和 redo log 的协调一致。基本上会出现下面是几种情况:
总结起来说就是如果一个事务在prepare阶段中落盘成功,并在MySQL Server层中的binlog也写入成功,那这个事务必定commit成功。
通过两阶段提交协议,MySQL 在事务提交过程中可以确保在发生崩溃时:
Binlog 记录事务提交的 SQL 操作,通常与 Redo Log 协同工作,实现崩溃一致性(Crash Consistency)。
MySQL 的 InnoDB 存储引擎 和 MySQL Server 层的 binlog 通过两阶段提交来保证事务的一致性,确保在系统崩溃或主从复制时,事务的逻辑和物理数据保持一致。
具体流程如下:
这个两阶段提交机制保证了 binlog 和 redo log 的协调一致。基本上会出现下面是几种情况:
总结起来说就是如果一个事务在prepare阶段中落盘成功,并在MySQL Server层中的binlog也写入成功,那这个事务必定commit成功。
通过两阶段提交协议,MySQL 在事务提交过程中可以确保在发生崩溃时:
在主从复制的场景下,binlog 的一致性尤为重要。
MySQL 确保:
通过这种机制,MySQL 保证了主从复制环境中的一致性,不会出现主库和从库不同步的情况。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。