第二十三章 MySQL是怎么保证数据不丢的?

2024-01-03 16:48

本文主要是介绍第二十三章 MySQL是怎么保证数据不丢的?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第二十三章 MySQL是怎么保证数据不丢的?

MySQL 能够保证数据不丢失的根据是什么 ?

根据 WAL 机制,只要 redo logbinlog 能保证持久化到磁盘,就能保证数据不丢失

binlog 的写入机制

binlog 是怎么写入磁盘的 ?

  • 事务执行过程中,先把日志写到 binlog cache,事务提交的时候,再把 binlog cache 写到 binlog 文件中
  • 事务执行过程中,每个线程会分配得到一片 binlog cache,由参数 binlog_cache_size 控制binlog cache 大小(如果超过,则会暂存到磁盘)
  • 并将记录写到 binlog cahce 中,由于一个事务中的 binlog 是不可拆分的,必须一次性全部写入
  • 所以 binlog cache 在 write 到 page cache 前,必定是全部收集事务记录完毕,并以事务为单位进行 write 工作
  • 下图 write,是把日志写入到文件系统的 page cache (写入文件内存页缓存),没有持久化到磁盘,所以速度比较快
  • 图中的 fsync,是将数据持久化到磁盘 (调用OS同步文件内存脏页到磁盘),占用磁盘的IOPS

Untitled

binlog 的同步日志到磁盘,有哪些设置参数,介绍一下 ?

  • 系统变量 sync_binlog
  • sync_binlog=0 的时候,表示每次提交事务都执行到 write(由OS决定 fsync 的时机)
  • sync_binlog=1 的时候,表示每次提交事务都会执行到 fsync
  • sync_binlog=N(N>1) 的时候,表示每次提交事务都执行到 write,然后 page cahce 中的binlog 记录凑齐 N 个事务后才执行 fsync
  • 注意:将 sync_binlog 设置为 N,如果主机发生异常重启,会丢失最近 N 个事务的 binlog 日志

为什么 binlog 写入数据是一次性全部写入,不能被打断 ?

  • binlog 写入的前提条件是事务被提交,事务至少进入了 prepare 状态
  • 如果一个事务的 binlog 能拆分写,则意味着在备库执行时,就相当于拆分成了多个事务段执行
  • 此时就破坏了事务的原子性,可能会导致一些不可预知的问题

redo log 的写入机制

redo log buffer 里面的内容,是不是每次生成后都要直接持久化到磁盘呢 ?

  • 不需要
  • 只有事务提交了才会从 redo log buffer 同步到 redo log 中
  • 事务执行过程中写入 redo log buffer,还没有提交,如果数据库崩溃,由于事务没有提交,因此会回滚,所以 redo log buffer 中数据丢失也没有关系

redo log 可能存在的三种状态 ?

Untitled

  • 存在 redo log buffer 中,物理上是在 MySQL 进程内存中,就是图中的红色部分
  • 写到磁盘 (write),但是没有持久化(fsync),物理上是在文件系统的 page cache 里面,也就是图中的黄色部分
  • 持久化到磁盘,对应的是 hard disk,也就是图中的绿色部分

redo log 的同步日志到磁盘,有哪些设置参数,介绍一下 ?

  • 系统变量 innodb_flush_log_at_trx_commit
  • 设置为 0 的时候,表示每次事务提交时都只是把 redo log 留在 redo log buffer
  • 设置为 1 的时候,表示每次事务提交时都将 redo log 直接持久化到磁盘
  • 设置为 2 的时候,表示每次事务提交时都只是把 redo log 写到 page cache

事务还没提交的时候,redo log buffer 中的部分日志有没有可能被持久化到磁盘呢 ?

  • 有可能
  • InnoDB 有一个后台线程,每隔 1 秒,就会把 redo log buffer 中的日志,调用 write 写到文件系统的 page cache,然后调用 fsync 持久化到磁盘
    • 事务执行中间过程的 redo log 也是直接写在 redo log buffer 中的,这些 redo log 也会被后台线程一起持久化到磁盘
    • 也就是说,一个没有提交的事务的 redo log,也是可能已经持久化到磁盘的
  • 如果 redo log buffer 大小达到 innodb_redo_log_buffer_size 的大小(16MB)的一半,则后台线程会主动写盘
    • 注意:由于事务还没有提交,因此不会持久化到磁盘,仅写到文件系统缓存页 (page cache)
  • 如果 innodb_flush_log_at_trx_commit 设置为1,则事务提交时,会将其他事务尚未提交的 redo log buffer 中的记录全部持久化到磁盘中

innodb_flush_log_at_trx_commit 设置为1时,为什么 redo logprepare 阶段就要持久化一次到磁盘 ?

  • 为1时,是保证所有 redo log 记录不丢失
  • MySQL 可以根据 redo log 的 prepare 和 对 binlog 的判定来判断事务是否生效
    • binlog 写完,redo log 还没 commit 前发生 crash
      • 如果 redo log 里面的事务是完整的,也就是已经有了 commit 标识,则直接提交
      • 如果 redo log 里面的事务只有完整的 prepare,则判断对应的事务 binlog 是否存在并完整:a. 如果是,则提交事务;b. 否则,回滚事务
  • 因此 prepare 阶段的 redo log 也是可以起到数据恢复作用的

innodb_flush_log_at_trx_commit 设置为1时,为什么说事务 commit 阶段不用再 fsync 到磁盘了 ?

  • 事务的 commit 阶段指的是事务提交过程中,最后 redo log 被标记为 commit 的阶段
  • 后台线程每隔1秒会将 redo log buffer 中的数据刷到 page cahce,再 fsync磁盘
  • 此时这些记录包含了 prepare 标识的数据,但 MySQL 在重放日志时候,可以根据 redo log的 prepare 标识再判断 binlog 的完整性等等从而进行恢复
  • 所以这时候,这些 prepare 表示的 redo log 提交时,就不会再fsync到磁盘一次
  • 这样做的目的是减少磁盘IO开销

什么是 MySQL 的双1设置 ?

  • sync_binloginnodb_flush_log_at_trx_commit 都设置成 1
  • 一个事务完整提交前,需要等待两次刷盘:
    • redo log(prepare 阶段)持久化到磁盘
    • binlog 持久化到磁盘

组提交(group commit)

介绍一下日志逻辑序列号 ?

  • log sequence number,简称 LSN
  • LSN 是单调递增的,对应每个 redo log 的写入点,值为上一个写入点 + 本次写入的 redo log 长度
  • LSN 也会写到 InnoDB 的数据页中,来确保数据页不会被多次执行重复的 redo log

两阶段提交

Untitled

写 binlog 其实是分成两步的:

  • 先把 binlog 从 binlog cache 写到内存中的 page cache
  • 调用 fsync 持久化到磁盘上的 binlog 文件

对于组提交中,组员越多,节约IOPS效果越好这一点,你知道MySQL还做了什么优化吗 ?

Untitled

  • binlog 执行 fsync 时,也会将其他的位于 page cache 的 binlog 一并进行 fsync,但由于 binlogwritefsync 间隔很短,所以往往效果不明显
  • MySQL 提供了两个参数:
  • binlog_group_commit_sync_delay 参数,表示延迟多少微秒后才调用 fsync
  • binlog_group_commit_sync_no_delay_count 参数,表示累积多少次以后才调用 fsync

WAL 机制是减少磁盘写,但是每次提交事务都要写 redo log 和 binlog,这样读写次数不是很多吗 ?

WAL 机制主要得益于两个方面:

  • redo log 和 binlog 都是顺序写,磁盘的顺序写比随机写速度要快
  • 组提交机制,可以大幅度降低磁盘的 IOPS 消耗

如果你的 MySQL 现在出现了性能瓶颈,而且瓶颈在 IO 上,可以通过哪些方法来提升性能呢 ?

  • 将 binlog 的提交延迟设置大一点,增加组提交的组员,减少写盘次数
  • sync_binlog 设置为大于1的值,但这可能导致出现数据丢失的风险(主机宕机时)
  • innodb_flush_log_at_trx_commit 设置为2,但这可能导致出现数据丢失的风险(主机宕机时)

设置 innodb_flush_log_at_trx_commit 为 0 会怎么样 ?

  • 不建议把 innodb_flush_log_at_trx_commit 设置成 0
  • 设置成 0,表示 redo log 是保存在 MySQL 进程中的内存缓存的,如果 MySQL 异常重启数据直接就丢失了
  • 设置成 2,表示 redo log 是写到了操作系统的 page cache了,会在合适时候 fsync 到磁盘,所以即使MySQL 进程重启了也不影响

为什么 binlog cache 是每个线程自己维护的,而 redo log buffer 是全局共用的 ?

  • binlog 是不能“被打断的”。一个事务的 binlog 必须连续写,因此要整个事务完成后,再一起写到文件里
  • binlog 是一种逻辑性的日志,记录的是一个事务完整的语句
  • 当用来做主从同步时,如果分散写,可能造成事务不完整,分多次执行,从而导致不可预知的问题
  • 而 redo log 属于物理性的日志,记录的是物理地址的变动。因此,分散写也不会改变最终的结果

事务执行期间,还没到提交阶段,如果发生 crash 的话,redo log 肯定丢了,这会不会导致主备不一致呢 ?

  • 不会
  • 因为这时候 binlog 也还在 binlog cache 里,没发给备库
  • crash 以后 redo log 和 binlog 都没有了,从业务角度看这个事务也没有提交,所以数据是一致的

一个极端的场景:若事务提交后,binlog 写完,主库同步 binlog 给备库执行,但主库尚未给客户端答复时,主库挂掉了,那么事务算失败了吗 ?

  • 不算,此时客户端会收到网络连接失败的反馈
  • 数据库的 crash-safe 保证的是:
    • 如果客户端收到事务成功的消息,事务就一定持久化了
    • 如果客户端收到事务失败(比如主键冲突、回滚等)的消息,事务就一定失败了
    • 如果客户端收到 “执行异常” 的消息,应用需要重连后通过查询当前状态来继续后续的逻辑。此时数据库只需要保证内部(数据和日志之间,主库和备库之间)一致就可以了

这篇关于第二十三章 MySQL是怎么保证数据不丢的?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/566392

相关文章

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份