前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mysql学习笔记【日志】

Mysql学习笔记【日志】

原创
作者头像
Porco1Rosso
修改2020-12-10 17:55:32
8180
修改2020-12-10 17:55:32
举报
本文为极客时间《Mysql实战45讲》的学习笔记,并结合《高性能Mysql》,梳理了索引相关的知识点,总结了一些常见问题,并记录了一些比较实用的方法。
Mysql 日志相关-2.png
Mysql 日志相关-2.png

三种常见的日志类型

RedoLog 重做日志

RedoLog是重要日志,是InnoDB用来做事务持久化的日志。他主要记录了事务在某个数据页上具体做了什么。它可以实现事务的crash-safe

结构
redo_log 日志结构.png
redo_log 日志结构.png
  • Write pos 是当前记录的位置,一边写一边后移,写到ib_logfile_3 号文件末尾后就回到 ib_logfile_0 号文件开头。
  • checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。
  • write poscheckpoint 之间的是还空着的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,表示日志满了,这时候不能再执行新的更新,得停下来先擦掉一些记录(刷脏页),把 checkpoint推进一下。

他的大致结构:

代码语言:txt
复制
show engine innodb status\G

---
LOG
---
Log sequence number          17680223 #代表系统中的lsn值,也就是当前系统已经写入的redo日志量
Log buffer assigned up to    17680223
Log buffer completed up to   17680223
Log written up to            17680223
Log flushed up to            17680223 #代表flushed_to_disk_lsn的值,也就是当前系统已经写入磁盘的redo日志量
Added dirty pages up to      17680223
Pages flushed up to          17680223 #代表flush链表中被最早修改的那个页面对应的oldest_modification属性值
Last checkpoint at           17680223 #checkpoint 的值
16 log i/o's done, 0.00 log i/o's/second
RedoLog Buffer 与写入机制

RedoLog Buffer的block由三部分组成:header(12字节),body(496字节),trailer(字节)。多个block组成了RedoLog Buffer。他的大小可以由innodb_log_buffer_size的大小来控制,默认时16M。

正常情况下,一个事务产生的RedoLog要先写入到RedoLog Buffer中,直到事务COMMIT才会被写入到磁盘中。多个事务产生的RedoLog也不是顺序存储的,而是随机存储的。他刷盘的策略有:

  1. 如果此时的RedoLog已经占用了RedoLog Buffer一半以上的内存,就要进行刷盘。
  2. 事务提交时,会把相关的记录刷盘
  3. 后台线程会定时刷盘
  4. 正常关闭服务时会刷盘
一些注意事项

关于RedoLog的一些配置:

  • 可以通过参数innodb_log_files_in_group来改变文件个数,这个参数的默认值是2;
  • 可以通过参数innodb_log_file_size来指定每个redo日志的大小;
  • 可以通过参数innodb_log_group_home_dir指定redo日志所在的目录。

RedoLog并没有参与到正常流程下的数据落盘的过程。这个问题涉及到RedoLog究竟存了些什么。

实际上,数据最终落库是以一页数据为单位进行写入磁盘的,RedoLog本身并没有记录一页完整的数据,而是记录了一页上面的数据都发生了什么变化。因此不能实现写入磁盘的功能。

  • 正常情况下的脏页刷盘和RedoLog没有任何关系
  • 崩溃恢复的时候,先把数据页读取到内存,然后通过RedoLog恢复页面发生的操作。此时页面变回脏页,再次落盘时和第一种情况一样。

innodb_flush_logs_at_trx_commit 的作用

  • 0,每次提交的事务只将RedoLog存储在RedoLog Buffer中,一秒后再持久化。性能很高,异常时可能会丢失1s 的日志,
  • 1,每次提交的事务都持久化到磁盘。write + fsync 最常用。性能不高,但是安全,理论上不存在丢数据的可能。
  • 2,每次都把RedoLog写到pagecache中,不fsync也就是说,把持久化交给了操作系统。Mysql服务崩溃了不会有影响。操作系统崩了,可能要丢数据了。

BinLog 重要日志

BinLog 是服务层的日志,相对而言实现起来比较简单,他不能提供crash-safe的功能。、

运行原理

BinLog 的写入逻辑比较简单:事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 BinLog文件中。

一个事务的 BinLog是不能被拆开的,因此不论这个事务多大,也要确保一次性写入。

这就涉及到了 binlog cache 的保存问题:

  1. 系统给binlog cache 分配了一片内存,每个线程一个,参数 binlog_cache_size 用于控制单个线程内 binlog cache 所占内存的大小。如果超过了这个参数规定的大小,就要暂存到磁盘。
  2. 事务提交的时候,执行器把 binlog cache 里的完整事务写入到 BinLog 中,并清空 binlog cache
注意事项

参数 sync_binlog 控制的:

  1. sync_binlog=0 的时候,表示每次提交事务都只 write,不 fsync
  2. sync_binlog=1 的时候,表示每次提交事务都会执行 fsync
  3. sync_binlog=N(N>1) 的时候,表示每次提交事务都 write,但累积 N 个事务后才 fsync

BinLog 落进文件分成两步:

  1. 把日志写入到文件系统的 page cache,并没有把数据持久化到磁盘,所以速度比较快。
  2. fsync将数据持久化到磁盘。一般情况下,我们认为 fsync 才占磁盘的 IOPS

UndoLog

回滚日志也是InnoDB实现的,目的是为了进行事务回滚,只要用在MVCC的时候。在数据修改的流程中,会记录一条与当前操作相反的逻辑日志到UndoLog中(可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录)。

日志写入用到的技术方案

WAL 机制

WAL 介绍

WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

如何理解Mysql中的WAL技术

关键点:将写入拆分为多步,先写日志,空闲时间再写磁盘,提高写效率。

代码语言:txt
复制
update user set a = 1 where b =2;

以一条更新语句为例,修改并不会直接写入这行数据所在的数据库文件(在硬盘中)。而是先写入到redolog日志。会有其他线程把redolog 的日志写入到硬盘中。当我们执行完这条语句,此时对于这条数据的修改,没有直接刷进其所在的数据页,他现在存在两个地方:change buffer (内存)和redo_log(磁盘) 中。当我们下一次查询的时候会先读change buffer 中的变动,对数据做merge。如果服务挂了,内存没有了,服务再次启动时,会先把redo_log 中的变动更新到数据库文件中,此时数据依然是修改后的状态。这个过程叫做:crash-safe。

那么为什么不直接写入到数据库文件呢?

第一,为了提高写入磁盘的效率;第二,提高并发。

数据库最大的性能瓶颈在于磁盘IO效率。充分利用磁盘IO,提高效率基本上有三个方法:

  • 随机读写改顺序读写
  • 缓冲单条读写改批量读写
  • 单线程读写改并发读写 WAL本质上就是这三个优化的集中体现。这个设计思路在我们日常工作中也非常有用。尤其是需要高并发写入的同时又要保证数据一致的时候。
WAL的优点
  • 读和写可以并发执行,不会阻塞。
  • WAL 可以降低写磁盘的成本,在保证数据一致性的同时,提高效率。
  • 有效减少了磁盘的随机IO,减少了fsync的次数

两阶段提交

两阶段提交是分布式系统中比较常见的一种事务提交算法。在Innodb的日志提交时用到了这个协议,用来保证事务提交时,redolog和binlog 都处于完成状态。具体而言:

  1. 操作完更新语句,把数据保存到内存
  2. 写入RedoLog,处于prepare阶段
  3. 写入BonLog
  4. 提交事务,BinLog和RedoLog都处于完成状态。

这里可以仔细推敲下,异常无论发生在12 之间还是其他之间,都可以保证下次恢复现场时数据的完整性。因为只有BinLog和RedoLog都存在的事务操作记录才是正确的。

两阶段提交我们在自己的服务开发中也有可能会使用到,这里还有维基-三阶段提交可以参考下

常见问题

BinLog与RedoLog 有哪些区别?

首先要先说明白,他们两个在目前InnoDB中是缺一不可的。少了哪一个都会出现问题。其次,他们之间至少有三点有很大的区别:

  1. RedoLogInnoDB 引擎特有的;binlogMySQLServer 层实现的,所有引擎都可以使用。
  2. RedoLog 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
  3. RedoLog 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

最后,简单说下:如果没有了RedoLog,数据就无法做到crash-safe,因为 binlog不具备保存事务的性质,最重要的是它并不具备记录数据页上究竟发生了什么。如果没有 binlog的话,RedoLog是个循环写入的,不存在归档这个功能。

RedoLog如何保证 crash-safe的?

我们先说下,如果没有RedoLog的话,数据怎么就丢了。假设,我们执行完一个事务,更新了一条数据。根据之前的笔记,这时候这条数据所在的数据页 一定保存在内存中,且是一个脏页,并没有被回写到磁盘里。此时的数据是不安全的,假如Mysql异常挂掉了,内存中的数据就没了。这个时候我们的更新就会丢掉。

加上RedoLog以后,我们执行完事务,此时就直接把操作记录保存在RedoLog中,并且已经被保存进磁盘了。事务提交后,RedoLog也就处在完成状态了。这个时候的状态是:虽然我们改过的数据还在内存中,没有刷盘,但是我们操作记录已经写进日志并持久化了。当出现异常后,虽然内存没了,但是服务启动后可以根据RedoLog恢复现场,这样就不会出现数据丢失了。

什么时候会刷脏页?

  1. RedoLog写满时,需要暂停更新操作。此时会停止所有的写入操作!
  2. 机器的物理内存满了的时候
  3. Mysql处于空闲状态时
  4. Mysql重启时

RedoLog和BinLog是如何配合工作的?

它们有一个共同的数据字段,叫 XID。崩溃恢复的时候,会按顺序扫描 RedoLog

  • 如果碰到既有 prepare、又有 commitRedoLog,就直接提交;
  • 如果碰到只有 prepare、而没有 commitRedoLog,就拿着 XID 去BinLog 找对应的事务。

RedoLog和BinLog常用的配置说明

  • N=1,1 适合数据安全性要求非常高,而且磁盘IO写能力足够支持业务,比如充值消费系统;
  • N=1,0 适合数据安全性要求高,磁盘IO写能力支持业务不富余,允许备库落后或无复制;
  • N=2,0或2,m(0<m<100) 适合数据安全性有要求,允许丢失一点事务日志,复制架构的延迟也能接受;
  • N=0,0 磁盘IO写能力有限,无复制或允许复制延迟稍微长点能接受,例如:日志性登记业务;

当两个参数设置为双1的时候,写入性能最差,sync_binlog=N (N>1 ) innodb_flush_log_at_trx_commit=2 时,MySQL的写操作才能达到最高性能。

一些参考

MySQL :: MySQL 8.0 Reference Manual :: 15.6.5 Redo Log

Mysql中的Redo Log解析(一) - 云+社区 - 腾讯云

Mysql中的Redo Log解析(二) - 云+社区 - 腾讯云

MySQL中的Redo Log(三) - 云+社区 - 腾讯云

使用O_DIRECT_NO_FSYNC来提升MySQL性能 - 知乎

维基-两阶段提交

innodb_flush_log_at_trx_commit和sync_binlog参数详解

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 三种常见的日志类型
    • RedoLog 重做日志
      • 结构
      • RedoLog Buffer 与写入机制
      • 一些注意事项
    • BinLog 重要日志
      • 运行原理
      • 注意事项
    • UndoLog
    • 日志写入用到的技术方案
      • WAL 机制
        • WAL 介绍
        • 如何理解Mysql中的WAL技术
        • 那么为什么不直接写入到数据库文件呢?
        • WAL的优点
      • 两阶段提交
      • 常见问题
        • BinLog与RedoLog 有哪些区别?
          • RedoLog如何保证 crash-safe的?
            • 什么时候会刷脏页?
              • RedoLog和BinLog是如何配合工作的?
                • RedoLog和BinLog常用的配置说明
                • 一些参考
                相关产品与服务
                云数据库 SQL Server
                腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档