| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 【MySQL】redo、undo、binlog日志的作用和实现原理 -> 正文阅读 |
|
[大数据]【MySQL】redo、undo、binlog日志的作用和实现原理 |
🌟 前言
文章目录1 概述日志是 MySQL 数据库的重要组成部分。MySQL 日志记录了 MySQL 数据库日常操作和错误信息。MySQL 有不同类型的日志文件(各自存储了不同类型的日志),从日志当中可以查询到 MySQL 的运行情况、用户的操作、错误的信息等。且当 MySQL 意外宕机时,可以通过这些日志文件进行数据恢复。 1.1 日志分类MySQL 主要包含一下六种日志:
对于主从复制结构中的 Slave 节点,还有一种 delay log(中继日志)。 1.2 日志作用其中 redolog 和 undolog 与 MySQL 的事务操作息息相关,binlog 主要应用于主从复制,当然与事务操作也有一定的关系,理解这三种日志,对理解 MySQL 中的事务操作有着重要的意义。 1.2.1 错误日志错误日志记录着 MySQL 启动和停止,以及服务器在运行过程中发生的错误及警告相关信息。当数据库意外宕机或发生其他错误时,我们应该去排查错误日志。 错误日志是默认开启的,可通过
1.2.2 慢查询日志慢查询日志是用来记录执行时间超过
慢查询日志默认是不开启的,但一般情况下建议开启,方便进行慢 SQL 优化。 1.2.3 一般查询日志一般查询日志又称通用查询日志,是 MySQL 中记录最详细的日志,该日志会记录 MySQL 服务器所有操作,包括客户端何时连接和断开服务器,并记录从客户端收到的每个 SQL 语句。 默认情况下也是关闭的,开启通用查询日志会增加很多磁盘 I/O, 所以如非出于调试排错目的,不建议开启通用查询日志。 2 redo 日志InnoDB 有一个最重要的概念就是缓冲池,这是一个在内存中分配的区域,InnoDB 会将数据首先缓存在此,请求首先去命中缓冲池,无法命中缓冲池的才会在磁盘上进行检索,被检索到的数据还是会缓存在缓冲池中。 但此时也引入了一个问题,如果由于某种原因导致 MySQL 宕机还未来得及刷页的话就会导致数据丢失,因此引入了重做日志。因此 redolog 不同于其它日志,是作用在 InnoDB 存储引擎层次上的。 redolog 记录的是数据库中每个页的修改,而不是某一行或某几行修改成怎么样,可以用来恢复提交后的数据页,并且只能恢复至最后一次提交的位置。 2.1 整体流程redo 日志并非直接写入磁盘,而也有对于的日志缓冲区。MySQL 服务器在启动时就会申请一块叫做 redo log buffer 的连续内存空间,并被分为若干 redo log block(一块 512k 的空间,用于存储一个不可分割的过程 MTR)。 redolog 对于 redo log buffer 采用循环写入的方式,即当 redolog 写满后从头开始写,形成一个环状。因为 redolog 记录的是数据页上的修改,如果缓存池的数据页已经刷盘了,那 redolog 中记录的信息就失去了价值,新日志就可将这些失效记录进行擦除覆盖。 缓存中未刷到磁盘的数据称为脏数据(dirty data)。由于数据和日志都以页的形式存在,所以脏页包含脏数据和脏日志。 write pos 和 check point 之间的绿色部分表示空余部分,用来记录写的日志,check point 到 write pos 之间是还未来得及刷盘的部分。当 write pos 追上 check point 时,就需要推动 check point 前移,即进行刷盘空出位置进行记录新的日志。 可以通过
当 redolog 写满进行擦除前,需要确认这些要被擦除的数据对应内存中的数据页都已经全部落盘。并且擦除记录这段期间不能接受更新请求,必然会导致 MySQL 性能下降。所以在高并发场景下,合理的调整 redolog 大小非常重要。 2.2 持久化MySQL 通过 Force Log at Commit 机制实现事务的持久性。即当事务提交时,先将 这样带来两个方面的好处:
2.3 刷盘策略redo buffer 以何种策略持久化到 redolog 可以通过
另外,InnoDB 存储引擎有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的内容写到文件系统缓存(page cache),然后调用 fsync 刷盘。 此外,当 MySQL 启动时,无论上次是正常关闭还是异常退出,都会进行恢复操作,先检查数据页中的 LSN,如果这个 LSN 小于 redolog 中的 LSN(write pos)位置,则说明 redolog 上存在未完成刷盘的记录,此时会从最近的 check point 出发开始同步数据。 2.4 两次写功能当发生数据库宕机时,可能存在 InnoDB 正在写入某个页到表,而这个页只写了一部分之后就发生了宕机的情况,这种情况被称为部分写失效(partial page write)。 部分写失效的问题,依靠重做日志无法恢复,因为重做日志是基于偏移量的物理操作,如果这个页本身已经发生了损坏,再对其进行重做是没有意义的。此时在使用重做日志前,用户如果有一个页的副本,当发生写入失效时,可以先通过页的副本来还原该页再进行重做,这就是 doublewrite。 doublewrite 由 内存中的 doublewrite buffer,大小为2MB 和物理磁盘上共享表空间中连续的 128 个页,即 2 个区(extent),大小同样为 2MB 两部分组成。 当刷新缓冲池脏页时,并不直接写到数据文件中,而是按照下面的路程执行: 1)拷贝页数据至内存中的两次写缓冲区。 2)从两次写缓冲区分两次写入磁盘共享表空间中,每次 1MB。 3)待第2步完成后,再将两次写缓冲区写入数据文件。 这样就可以解决部分写失效的问题,因为在磁盘共享表空间中已有数据页副本拷贝,如果数据库在页写入数据文件的过程中宕机,在实例恢复时,可以从共享表空间中找到该页副本,将其拷贝覆盖原有的数据页,再应用重做日志即可。 其中第 2 步是额外的性能开销,但由于磁盘共享表空间是连续的,因此开销不是很大。可以通过 3 undo 日志前面我们讲到 redolog 可以在服务器意外宕机时用来恢复数据,保证已提交事务的持久性。但可能出现在事务还未提交的时候,写入的 redolog 已经被刷盘的情况,那么这些未提交的事务在 MySQL 重启时也被跟着恢复了,这样就违背了事务的原子性。 为了解决这个问题,InnoDB 又引入了另一种事务日志,即回滚日志,用于记录数据修改前的状态。在数据修改的流程中,记录一条与当前操作相反的回滚日志。即 redolog 是物理日志,而 undolog 是逻辑日志。
1)实现事务原子性,利用 undolog 进行回滚; 2)实现 MVVC 机制:undolog 中保存了未提交之前版本数据,所以可以作为旧版本数据的快照以便其他事务进行读取。
与 redolog 存放在重做日志文件不同的是,undolog 存放在数据库内部的一个特殊的段(segment)中,称为 undo segment。undo 段位于共享表空间内。InnoDB 对 undo 的管理同样采用段的方式,称为 rollback segment,每个回滚段记录了 1024 个 undo 段。(5.6.3 之后可通过
在 InnoDB 存储引擎中,undolog 又被分为 insert undo log 和 update undo log。 insert undo log 是指在 insert 操作中产生的 undolog,因为 insert 操作的记录只对事务本身可见,对其他事务不可见,故该 undolog 可以在事务提交后直接删除,不需要进行 purge 操作。 而 update undo log 记录的是对 delete 和 update 操作产生的 undo log,该日志可能需要提供 MVCC 机制,因此不能再事务提交时就进行删除。提交时放入 undolog 链表,等待 purge 线程进行最后的删除。(purge 线程两个主要作用是:清理 undo 页和清除 page 里面带有 Delete_Bit 标识的数据行) 需要注意的是,假如一个事务中一条记录被多次修改,但是 undolog 只会记录原始版本的一条数据,每当对数据进行修改时,都会写入 redolog。 4 binary 日志前面我们介绍的介绍的 redo 日志和 undo 日志都是在 InnoDB 引擎上的日志,而 binlog 则是在 Server 层进行操作的日志。因为在 MySQL 5.5 之前默认前使用的 MyISAM 引擎,并不支持事务,所以 InnoDB 只能自己实现一套新的日志系统。 4.1 基础概述
binlog 以二进制形式存储在磁盘中的逻辑日志,记录了所有 DDL 和 DML 操作(不包括 select 和 show),默认情况下是关闭的。主要作用于主从同步以及基于时间点的数据还原。
1)主库执行 DDL 和 DML 操作,按照修改顺序以此写入 binlog。 2)从库的 IO 线程连接上主库并请求读取指定位置 position 的日志内容。 3)主库收到请求后,将指定位置 position 之后的内容日志、主库 binlog 文件名称以及在日志中的位置推送给从库。 4)从库 IO 线程收到数据后,将日志内容以此写入 relaylog 文件最末端,并将 binlog 文件名和位置 position 记录到 master-info 文件中,以便下次使用。 5)从库的 SQL 线程检测到 relaylog 中内容更新后,读取日志并解析成可执行的语句进行主从同步。
4.2 redolog一条 1)先查到对应数据 A 的主键 id = 2,通过主键索引来找到这条数据所在的页号。然后在 Buffer Pool 中进行查询,如果查到,则直接操作,如果查不到,则从磁盘内进行读取。 2)执行器拿到引擎给的这条数据进行 +1 操作后,再调用引擎接口写入这条数据。 3)引擎将这条数据更新至内存,同时记录到 redolog,此时 redolog 处于 prepare 态,这就告诉执行器更新已经完成,随时可以提交事务。 4)执行器生成这个操作的 binlog ,并把 binlog 写入磁盘。 5)执行器调用引擎的事务接口,引擎把刚刚的 redolog 改为提交状态,这个事务执行完成。
如果没有两阶段提交,无论先写 redolog 还是先写 binlog 都会导致 redolog 和 binlog 记录的操作不一致,那么数据库的状态就有可能和日志恢复出来的数据不一致。 此时 MySQL 数据恢复过程: 1)读取 redo 日志,并从 checkpoint 开始重放(重新在内存中执行对应数据页的修改,然后按照正常流程进行数据刷盘)。 2)检查 redolog 中处于 prepare 状态的完整事务。 3)通过这些事务的 xid 在 binlog 中查询事务是否完整,完整则在 redolog 中设置为 commit 状态,否则根据 xid 在 undolog 找到事务并进行回滚。
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 5:38:40- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |