前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mysql 异常情况下的事务安全 -- 详解 mysql redolog

mysql 异常情况下的事务安全 -- 详解 mysql redolog

作者头像
用户3147702
发布2022-06-27 14:03:05
4850
发布2022-06-27 14:03:05
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

上一篇文章中,我们介绍了 mysql 的二进制日志 binlog,他为数据的同步、恢复和回滚提供了非常便利的支持。 怎么避免从删库到跑路 — 详解 mysql binlog 的配置与使用

无论我们使用的是什么存储引擎,只要通过配置开启,mysql 都会记录 binlog。 在工程存储项目中,有一个重要的概念,那就是 crash safe,即当服务器突然断电或宕机,需要保证已提交的数据或修改不会丢失,未提交的数据能够自动回滚,这就是 mysql ACID 特性中的一个十分重要的特性 — Atomicity 原子性。 根据我们上一篇文章中的讲解,依靠 binlog 是无法保证 crash safe 的,因为 binlog 是事务提交时写入的,如果在 binlog 缓存中的数据持久化到硬盘之前宕机或断电。 在服务器恢复工作后,由于 binlog 缺失一部分已提交的操作数据,而主数据库中实际上这部分操作已经存在,从数据库因此无法同步这部分操作,从而造成主从数据库数据不一致,这是很严重的。 但实际上,innodb 存储引擎是拥有 crash safe 能力的,那么他是用什么机制来实现呢?本文我们就来详细说明。

2. mysql 的执行过程

无论使用任何存储引擎,只要开启相应配置,mysql 都会记录 binlog。 但 MyISAM 引擎并没有提供 crash safe 能力,而 InnoDB 则提供了灾后恢复能力,这是为什么呢? 这和 mysql 整体的分层有关,我们需要首先了解一下一条 sql 语句是如何执行的。

mysql 主要分为两层,与客户端直接交互的是 server 层,包括连接的简历和管理、词法分析、语法分析、执行计划与具体 sql 的选择都是在 server 层中进行的,binlog 就是在 server 层中由 mysql server 实现的。 而 innodb 作为具体的一个存储引擎,他通过 redolog 实现了 crash safe 的支持。

3. redolog 的写入

mysql 有一个基本的技术理念,那就是 WAL,即 Write-Ahead Logging,先写日志,再写磁盘,从而保证每一次操作都有据可查,这里所说的“先写日志”中的日志就包括 innodb 的 redolog。 redolog 与持续向后添加的 binlog 不同,他只占用预先分配的一块固定大小的磁盘空间,在这片空间中,redolog 采用循环写入的方式写入新的数据。

同时,binlog 是以每条操作语句为单位进行记录的,而 redolog 则是以数据页来进行记录的,他记录了每个页上的修改,所以一个事务中可能分多次多条写入 redolog。

4. crash safe 与两阶段提交

每条 redolog 都有两个状态 — prepare 与 commit 状态。 例如对于一张 mysql 表(CREATE TABLE A (ID int(10) unsigned NOT NULL AUTO_INCREMENT, C int(10) NOT NULL DEFAULT 0, PRIMARY KEY (ID)) ENGINE=InnoDB),我们执行一条 SQL 语句:

UPDATE A set C=C+1 WHERE ID=2

实际上,mysql 数据库会进行以下操作(下图中深色的是 mysql server 层所做的操作,浅色部分则是 innodb 存储引擎进行的操作):

可以看到,在写入 binlog 及事务提交前,innodb 先记录了 redolog,并标记为 prepare 状态,在事务提交后,innodb 会将 redolog 更新为 commit 状态,这样在异常发生时,就可以按照下面两条策略来处理:

  1. 当异常情况发生时,如果第一次写入 redolog 成功,写入 binlog 失败,MySQL 会当做事务失败直接回滚,保证了后续 redolog 和 binlog 的准确性
  2. 如果第一次写入 redolog 成功,binlog 也写入成功,当第二次写入 redolog 时候失败了,那数据恢复的过程中,MySQL 判断 redolog 状态为 prepare,且存在对应的 binlog 记录,则会重放事务提交,数据库中会进行相应的修改操作

整个过程是一个典型的两阶段提交过程,由 binlog 充当了协调者的角色,针对每一次日志写入,innodb 都会随之记录一个 8 字节序列号 — LSN(日志逻辑序列号 log sequence number),他会随着日志写入不断单调递增。 binlog、DB 中的数据、redolog 三者就是通过 LSN 关联到一起的,因为数据页上记录了 LSN、日志开始与结束均记录了 LSN、刷盘节点 checkpoint 也记录了 LSN,因此 LSN 成为了整套系统中的全局版本信息。 当异常发生并重新启动后,innodb 会根据出在 prepare 状态的 redo log 记录去查找相同 LSN 的 binlog、数据记录,从而实现异常后的恢复。

5. redo log 的组织

redo log 是以“块”为单位进行存储的,称之为“redo log block”,每个块的大小是 512 字节。 以块为单位存储的原因是他和磁盘扇区的大小是相同的,从而保证在异常情况发生时不会出现部分写入成功产生的脏数据。

6. 相关配置

6.1. innodb_log_file_size

redo log 磁盘空间大小,默认为 5M。

6.2. innodb_log_buffer_size

redo log 缓存大小,默认为 8M。

6.3. innodb_flush_log_at_trx_commit

此前我们曾经介绍过,操作系统为了减少了磁盘的读写次数,提升系统的 IO 性能,会在内存空间中分配一个缓冲区,这就是页面高速缓冲,虽然高速缓冲让 IO 性能得以大幅提升,但在宕机等异常发生时,这部分在高速缓冲区中的数据就会丢失,因此 unix 提供了系统调用 fsync。 来让我们手动执行高速缓冲到磁盘的刷新工作。 对于 redolog 来说,由于他的存在就是为了避免异常情况造成的已提交事务的丢失,所以高速缓冲引起的未刷盘数据丢失是不能容忍的,innodb_flush_log_at_trx_commit 配置项就是指定具体的刷盘策略的。 他有以下值可以选择:

  1. 0 — 以固定间隔将缓存中的数据写入系统高速缓存并调用一次 fsync 强制刷新高速缓冲,系统崩溃可能丢失最大1秒的数据
  2. 1 — 默认值,每次事务提交时调用 fsync,这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差
  3. 2 — 每次事务提交都将数据写入系统高速缓存,但仅在固定间隔调用一次 fsync 强制刷新高速缓冲,安全性高于配置为 0

通常,为了绝对的安全性,我们会配置为 1,但在追求最高的写入性能时,我们通常配置为 2,因为设置为 2 与设置为 0 在性能上差异不大,但配置为 2 却在安全性上高于配置为 0。 同时为了保证 binlog 的安全性,我们同时要配置 sync_binlog 为 1,保证每次 binlog 都直接写入磁盘,而不进行缓存。

6.4. innodb_flush_log_at_timeout

上面提到了刷新告诉缓存的固定间隔,这个“固定间隔”就是通过 innodb_flush_log_at_timeout 配置项指定的,默认是 1 秒。 但实际上,如果 redo log 的缓存占用超过一半,也会立即触发缓冲的刷新。

7.参考资料

https://www.jianshu.com/p/9d98dac77a2b。 https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html。 https://blog.csdn.net/GDUFZXP/article/details/84350363。 https://blog.csdn.net/shaochenshuo/article/details/73239949。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. mysql 的执行过程
  • 3. redolog 的写入
  • 4. crash safe 与两阶段提交
  • 5. redo log 的组织
  • 6. 相关配置
    • 6.1. innodb_log_file_size
      • 6.2. innodb_log_buffer_size
        • 6.3. innodb_flush_log_at_trx_commit
          • 6.4. innodb_flush_log_at_timeout
          • 7.参考资料
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档