MySQL日志的知识点有哪些

57次阅读
没有评论

共计 4446 个字符,预计需要花费 12 分钟才能阅读完成。

本篇内容主要讲解“MySQL 日志的知识点有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让丸趣 TV 小编来带大家学习“MySQL 日志的知识点有哪些”吧!

Mysql 的日志系统是 Mysql 保证无论何时崩溃数据都不会丢失的关键

众所周知 Mysql 是持久化的数据库, 所有的数据都是持久化到硬盘中的, 保证数据不会丢失

Mysql 保证数据不会丢失是从以下两个方面来体现的

能够恢复到任意时刻的数据状态

无论在事务提交前还是提交后崩溃都能保证数据不丢失

事务过程中崩溃能够恢复到事务提交前的状态

事务提交后崩溃已提交的数据不会丢失

MySQL 保证以上两个点的关键就是通过 undo log, redo log 和 binlog 这三个日志来实现的, 接下来将逐一介绍

undo log 回滚日志

undo log 是 Mysql 的回滚日志, 存储的是老版本的数据

主要作用

存储老版本的数据

配合 Read View 和隐藏字段实现了 Mysql 的快照读

用于在事务执行失败的时候回滚到事务开始前的版本

undo log 有什么类型

undo log 有两种类型

对于 insert 命令, undo log 记录的是新增的记录的主键, 在回滚的时候根据 undo log 中的主键去删除对应的记录即可

对于 update / delete 命令, undo log 记录的是被修改的记录的旧数据

Mysql 中的每一行数据都有一个最新修改当前数据行的事务 id 和回滚指针这两个字段, 当对数据行进行修改之后, undo log 指针就会指向旧的这一行数据, 而新生成的这一行数据的回滚指针就会指向 undo log 指针当前指向的旧数据行

Mysql 为了避免 undo log 指针修改指向的时候出现并发问题, 在修改之前会对 undo log 指针增加排他锁以保证 undo log 的正确写入

undo log 什么时候删除

undo log 是用于保证事务在未提交的时候可以顺利回滚到事务开始前的状态, 当事务提交之后 undo log 就失去作用了, 就需要被删除

undo log 是交由 Mysql 中的 Purage 线程来负责删除的, purage 会定期检查 undo log 中的 deleted_bit 标志, 这个标志会在事务提交后被设置为 true, purage 线程发现为 true 的记录就会负责将其删除

redo log 重做日志

redo log 是 Mysql 的物理日志, 负责记录某个数据页执行了什么样的操作

redo log 的作用

负责记录提交的事务对数据的修改, 记录的内容大概就是对 x 表的 y 页 z 偏移做了 a 更新

让 Mysql 在提交事务的时候无需等待数据持久化磁盘, 只需要将 redo log 持久化到磁盘就可以了

未清除的 redo log 的数量标识了未刷盘的脏页数量

为什么提交事务是选择持久化 redo log, 而不是持久化数据到磁盘

持久化数据到磁盘是随机 IO 过程, 所以 Mysql 选择将数据缓存起来, 等待一个合适的时机将数据一次性写入磁盘, 减少 IO

但是数据缓存在内存中有丢失的风险, 所以 Mysql 选择将 redo log 持久化

redo log 是顺序写, 持久化的效率比随机写的效率要高, 并且 redo log 记录了数据的变化情况, 只要 redo log 在就可以保证在 Mysql 重启后恢复数据

在 InnoDB 中, redo log 是一个固定大小的类似循环队列的存在, 每次写入都从后面 write pos 的位置, 在持久化数据的时候就移动 check point 往前读取

这样设计的原因是因为 redo log 是防止 Mysql 崩溃后缓存的脏页数据丢失而存在的

当 Mysql 中的数据被持久化到磁盘中后, 被持久化部分的 redo log 其实就没有用了, 就可以腾出空间来记录新的数据

undo log 和 redo log 的区别

undo log 记录的是事务执行过程中旧数据的状态, redo log 记录的是数据更新之后的状态

redo log 其实保障的是事务的持久性和一致性,而 undo log 则保障了事务的原子性

binlog 归档日志

binlog 是 Mysql server 层实现的日志, 是所有引擎通用的

作用

binlog 记录的是 mysql 原始的语句逻辑, 并且是采用追加写入的形式记录的, 所以可以用于恢复 mysql 在任意时刻的数据库数据状态

所以叫 binlog 是归档日志

同时 binlog 也是 Mysql 实现主从复制的依赖, 从库通过从主库中复制 binlog 回放来同步主库的数据状态

定义

先写日志到磁盘中, 再写数据到磁盘中 Mysql 的写操作不是立刻写入到磁盘中的, 而是先写日志, 保证 redo log 和 binlog 都持久化到磁盘中再由后台线程选择时机将数据持久化到硬盘的

为什么要先写日志到磁盘中

因为刷脏页是一个随机读写的过程, 持久化到磁盘中的速度肯定没有 redo log | binlog 这些顺序写的速度快, 所以选择先在内存中对数据进行修改, 再后期选择时机异步持久化到磁盘中

所以在脏页还未刷入磁盘中的这段时间就由 redo log | binlog 来保证数据的持久化, 防止断电重启等情况内存中的数据丢失

当脏页满的时候需要将脏页写入到磁盘再淘汰, 为何不全部淘汰掉下次使用的时候再通过 redo log 来恢复呢

从性能方面考虑的, 如果每次从磁盘中读取数据到内存都需要和 redo log 比对更新, 效率很低

MySQL 刷脏页写入到磁盘保证了数据页只要在内存中, 就肯定是当前最新的数据可以返回

如果内存中没有数据只要从磁盘中读取肯定能得到最新的正确数据, 而不用再去同 redo log 进行比对

binlog 和 redo log 的写入过程 – WAL 机制的基本保证

binlog 和 redo log 都是将日志写入划分为三个过程 写入 cache, write 和 sync

在事务执行过程中会将 binlog 和 redo log 写入到对应分配的缓存中, 以便在事务提交的时候一次性写入到磁盘中

在事务提交的时候会先进行 write 将数据写入到操作系统的页缓存中, 此时数据还未真正写入文件, 但是已经是交由操作系统的缓存来保管了, 如果此时 Mysql 进程崩溃这部分写入的数据也不会丢失, 操作系统的内核线程会负责将这部分缓存中的数据写入磁盘

但是如果操作系统崩溃了这部分数据就丢失了

最后就是 mysql 手动调用 sync 将写入在页缓存中的数据持久化到硬盘, 写入完成后数据就是持久化成功了

最后的 write 和 sync 步骤 mysql 提供了对应的参数来控制写入策略

redo log 是通过 innodb_flush_log_at_trx_commit 来控制的

设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log 的缓存中

丢失风险最大

设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘

丢失风险最小, 但是 IO 占用大

设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache

IO 占用居中, 将写入到磁盘这个最占用 IO 的过程交由操作系统来负责

binlog 是通过参数 sync_binlog 来控制的

sync_binlog=0 的时候,表示每次提交事务都只 write,不 fsync

sync_binlog=1 的时候,表示每次提交事务都会执行 fsync

sync_binlog=N(N 1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync

两阶段日志提交

什么是两阶段日志提交

将 redo log 日志提交的过程分为 prepare 和 commit 这两个阶段, binlog 日志提交在这两个阶段中间

事务提交时 redo log 先提交后进入 prepare 状态, 然后 binlog 提交完成后 redo log 才能将日志的状态修改为 commit 已提交

为什么需要两阶段日志提交

和 InnoDB 引擎的回滚机制有关, InnoDB 的 redo log 提交了事务就无法回滚了, 如果在 redo log 提交后 binlog 写入失败的话就会出现两份不统一的情况

如果此时数据库异常重启的话要依据那一份来恢复数据就值得思考了, 所以才需要两阶段日志提交

假设现在在时刻 A 数据库崩溃的话, 因为 binlog 还未写入, redo log 还未提交, 所以重启后事务会回滚, 两份日志依旧是统一状态

如果是时间段 B 的话, 就需要对 redo log 的提交标志进行判断了, 在查询 redo log 中是否有 commit 提交标志, 如果有的话事务没有问题, 直接提交

如果 redo log 中没有对应事务的提交标志的话会对 binlog 进行检查

如果 binlog 完整并且带有 commit 标志, 就会提交事务并在 redo log 后面补上 commit 标志如果 binlog 不完整就回滚事务

这里可以发现两阶段日志提交中发生了崩溃是依据 binlog 来进行标准判断的, 原因是因为主从复制是依据 binlog 来进行的

如果对两份日志都需要检查完整性的话, 主库挂掉切换到从库的时间会变长, 以 binlog 为基准的话主库挂了直接拿着 binlog 去从库恢复数据即可, 无需检查 redo log 的完整性

此外 binlog 是 Mysql Server 层的通用日志, 这也是选择 binlog 作为基准的原因

两阶段日志提交的缺点

磁盘 IO 次数高

在提交日志的时候会有 redo log 和 binlog 对应的刷盘操作, IO 次数高

锁竞争激烈

为了保证多个事务提交的时候日志的记录和事务的提交顺序是一致的, 会使用锁来保证日志提交的相对顺序

但是在并发量大的情况下性能会变差

组提交机制

组提交机制的作用

当有躲过事务提交的时候, 将多个事务的日志合并在一起去写入, 减少磁盘 IO 操作

组提交机制的实现

组提交机制将 commit 过程拆分成三个过程, 对每个过程都维护了一个队列, 并且通过锁来保证事务的写入顺序

分成三个阶段分别加锁可以减少锁粒度, 无需锁住事务的整个提交过程

当队列为空的时候第一个进入队列的事务会成为后续进入的事务的领导者, 带领后续事务完成接下来的阶段操作

阶段一 : flush 阶段 : 多个事务按进入的顺序将 binlog 从 cache 中写入文件 (不刷盘)

第一个进入 flush 阶段的事务会作为领导者领导后面进入的事务

领导者事务会带领所有的事务对 redo log 进行一次 write + fsync, 也就是将 redo log 写入磁盘, 完成 redo log 的 propare 阶段

如果在这个阶段 Mysql 崩溃了, 会在重启后回滚这组事务

阶段二 : sync : 对 binlog 文件做 fsync 操作 (将多个事务的 binlog 合并一起刷盘)

在 flush 阶段将 binlog 写入到 binlog 文件后, 会等待一段时间再进行刷盘, 目的是组合更多事务的 binlog 一起刷盘减少消耗

等待会有时间限制和最大事务限制, 满足其中一个条件就会立刻对 binlog 进行刷盘

sync 阶段主要负责 binlog 的组提交, 如果当前阶段 Mysql 崩溃的话, 在重启后可以通过 redo log 的刷盘记录继续完成事务提交

因为此时 binlog 已经完成提交了, 所以可以根据 redo log 来继续提交事务

阶段三 : commit : 对各个事务做 InnoDB 的 commit 操作

到此,相信大家对“MySQL 日志的知识点有哪些”有了更深的了解,不妨来实际操作一番吧!这里是丸趣 TV 网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-13发表,共计4446字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)