惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
F
Fox-IT International blog
C
Cisco Blogs
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
Malwarebytes
Malwarebytes
Latest news
Latest news
D
Darknet – Hacking Tools, Hacker News & Cyber Security
SecWiki News
SecWiki News
N
News and Events Feed by Topic
T
True Tiger Recordings
www.infosecurity-magazine.com
www.infosecurity-magazine.com
美团技术团队
P
Palo Alto Networks Blog
V
V2EX - 技术
AWS News Blog
AWS News Blog
A
About on SuperTechFans
Microsoft Azure Blog
Microsoft Azure Blog
量子位
博客园 - 【当耐特】
P
Proofpoint News Feed
N
News and Events Feed by Topic
博客园 - 司徒正美
U
Unit 42
G
Google Developers Blog
阮一峰的网络日志
阮一峰的网络日志
Schneier on Security
Schneier on Security
G
GRAHAM CLULEY
O
OpenAI News
T
The Blog of Author Tim Ferriss
F
Future of Privacy Forum
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
Blog — PlanetScale
Blog — PlanetScale
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News | PayPal Newsroom
V
Visual Studio Blog
V
V2EX
Simon Willison's Weblog
Simon Willison's Weblog
Microsoft Security Blog
Microsoft Security Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threat Research - Cisco Blogs
Spread Privacy
Spread Privacy
N
Netflix TechBlog - Medium
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
小众软件
小众软件
H
Hackread – Cybersecurity News, Data Breaches, AI and More
I
Intezer

郑文峰的博客

使用dify对接飞书多维表格 使用n8n对接飞书多维表格 服务启动时出现 OOM Bug 通缉令 一次服务升级时pg表DDL执行超时失败 Go语言高性能编程 Go语言高效IO缓冲技术详解 Go语言延迟初始化(Lazy Initialization)最佳实践 Go语言字符串拼接性能对比与优化指南 Go语言结构体内存对齐完全指南 Go语言空结构体:零内存消耗的高效编程 Go语言堆栈分配与逃逸分析深度解析 Go语言原子操作完全指南 Go语言内存预分配完全指南 Go语言不可变数据共享:无锁并发编程实践 Go语言零拷贝技术完全指南 Go语言遍历性能深度解析:从原理到优化实践 Go语言Interface Boxing原理与性能优化指南 Go协程池深度解析:原理、实现与最佳实践 使用etcd分布式锁导致的协程泄露与死锁问题 基于pre-commit的Python代码规范落地实践 初识 MCP Server pulsar阻塞导致logstash无法接入日志 django-prometheus使用及源码分析 kube-proxy源码分析 kubernetes service如何通过iptables转发 tcp缓存引起的日志丢失 django-apschedule定时任务异常停止 理解calico容器网络通信方案原理 理解flannel的三种容器网络方案原理 理解Linux IPIP隧道 理解VXLAN网络 理解Linux TunTap设备 快速了解iptables kafka中listener和advertised.listeners的作用 django rest_framework 分页 django后端服务、logstash和flink接入VictoriaMetrics指标监控 python中import原理 docker容器单机网络 手动实现docker容器bridge网络模型 mysql之MVCC原理 使用java开发logstash的filter插件 使用python实现单例模式的三种方式 redis之缓存 redis之分片集群 redis之哨兵机制 redis之主从库同步 redis之持久化 redis之五种基本数据类型 go中如何处理error pod中将代码与运行环境分离 友链 ddt源码分析 python装饰器的使用方法 读书笔记:如何阅读一本书 使用ddt实现unittest的参数化测试 分布式锁 使用kubeadm安装k8s 优化gin表单的错误提示信息 gin中validator模块的源码分析 go简单使用grpc python简单使用grpc k8s之PV、PVC和StorageClass k8s之StatefulSet k8s之DaemonSet k8s之Job和CronJob k8s之ConfigMap和Secret k8s之Service k8s之Pod k8s之Deployment 容器的本质 docker容器 python迭代器与生成器 python元编程 python垃圾回收机制 python上下文管理器 django rest_framework使用jwt django rest_framework异常处理 django rest_framework 自定义文档 django压缩文件下载 django rest_framework使用pytest单元测试 django restframework choice 自定义输出数据 django Filtering 使用 django viewset 和 Router 配合使用时报的错 django model的序列化 django中使用AbStractUser django.core.exceptions.ImproperlyConfigured Application labels aren't unique, duplicates users django 中 media配置 django 外键引用自身和on_delete参数 django 警告 while time zone support is active Flask使用flask_socketio实现websocket flask结合mongo tornado 文件上传 tornado 使用jwt完成用户异步认证 tornado 用户密码 bcrypt加密 tornado 结合wtforms使用表单操作 tornado finish和write区别 tornado 使用peewee-async 完成异步orm数据库操作 pyspark streaming简介 和 消费 kafka示例 使用hue创建ozzie的pyspark action workflow
mysql之日志
2023-01-01 · via 郑文峰的博客

# 前言

一条数据在更新过程当中,如果中途 mysql crash 了,mysql 是如何保证数据的一致性和持久性的?在这个过程中 mysql 的日志系统起到了至关重要的作用。本文将会介绍 mysql 中的 undo log、redo log 和 bin log 在这其中的作用。

# buffer pool

在数据更新的时候,数据并不是实时同步到硬盘中,而是在一块缓存 buffer pool 中更新,如果缓存中没有查询到该数据,则从磁盘中加载到 buffer pool 中。

当然,缓存的作用是为了提高 IO 性能,可以通过将数据先保留在缓存中,然后在适当的时机,批量写入到硬盘中。

并且在查询数据时,先是从缓存中进行查询,不用去磁盘中查找,减少 IO 的操作,加快查询的速度。

# undo log

我们知道 InnoDB 是支持事务的,在事务提交失败时,是会回滚到执行之前的状态,那么肯定是需要保存之前的状态才可以进行恢复的,这个就是通过 undo log 来实现的。

在数据写入 buffer pool 的同时会将更新前的数据保存在 undo log 中,通过该日志语句便可以在事务回滚时,恢复到之前的状态。

# redo log

# redo log 的作用

再回到 buffer pool ,因为它是缓存,是在内存中,所有它的缺点也显而易见,那就是当服务器宕机中,缓存中的数据会丢失,那么 mysql 是如何保证数据的持久性呢?这个时候就要来介绍介绍 redo log 了。

在数据更新到 buffer pool 后,这个时候会将更新后的数据记录到 redo log buffer 中,这个也是一个缓存区,它当然也具备了缓存优缺点,并且默认是在提交事务的时候写入到 redo log 中,刷盘的策略可以根据 innodb_flush_log_at_trx_commit 来设置

  • 0,不刷入磁盘
  • 1,立即刷入磁盘(默认)
  • 2,先刷入到 os cache 中

因为 redo log 是顺序写入,所以 IO 性能不会太差。

当 buffer pool 中的数据还没有写入到磁盘中时,发生了宕机,当 mysql 重启时,会读取已经持久化 redo log 中的数据,再恢复到 buffer pool 中。

在开启事务准备更新一条记录时,InnoDB 会先在 buffer pool 中更新数据,然后将更新后的数据记录到 redo log buffer 中,这也是一个缓存。当然这个时候也是会发生宕机,但是没关系,如果该部分数据丢失,则认为该次事务提交失败,数据会恢复到之前的状态。

# redo log文件结构

redolog 是由多个固定大小的文件组成的一个环形结构,并在这个环形结构中不断的写入与覆盖的过程。

  • write pos:记录当前的位置
  • checkpoint:当前要擦除的位置

当有新的 redo log 写入时,从 wirte pos 位置往后写,而 check point 是上一次已经刷入磁盘的数据的位置,也是要不断的往后推进,然后将数据刷入磁盘中。

# binlog

是在 mysql 层级记录的日志,主要是用于主从复制和数据恢复,可以通过某个时间的全量备份+binlog 来恢复到任意时间内的状态。

和 redo log 的区别

性质 redo log bin log
实现 innodb 独有实现 mysql server 层级实现,所有的引擎都可以使用
内容 物理 log, 记录的是“在某个数据页上做了什么修改” 逻辑 log,给 ID=2 这一行的 c 字段加 1
写入 循环写入 追加写,写到一定大小切换下一个文件继续写
应用 崩溃恢复(crash-safe) 主从同步,数据恢复

# 两阶段提交

为什么需要两阶段提交?

是为了让 redo log 和 bin log 保持逻辑一致性。

  1. 如果先写 redolog 后写 bin log。假设 redo log 写完,写 bin log 时 crash 了。

因为 redo log 写完了,所以即使系统崩溃,也可以恢复数据,但是 bin log 没写完 crash 了,这个时候 bin log 中少了该条语句,因此数据备份的时候,如果使用了该份 bin log 则会少一次更新。

  1. 如果先写 bin log 后写 redo log。假设 bin log 写完,写 redo log 时 crash 了。

因为 redo log 没写完,所以该事务没有生效,但是 binlog 中已经有该条记录,所以使用 bin log 时,会多出一个事务,与原来的数据不一致。

所以使用两阶段提交可以解决上面两种场景。

两阶段提交的实现逻辑

  1. 在更新数据时,会先在 redo log 中记录当前更新的数据,并且标记为 prepare 状态
  2. binlog 再进行写入
  3. 事务提交时, redo log 再将该条记录标记为 commit 状态并且刷入到磁盘中。

通过 prepare 和 commit 两种状态来完成两阶段的提交实现。

验证两阶段提交

  1. 如果在两阶段提交的第一步后发生 crash,也就是 redo log 已经更新了数据并且为 Prepare 状态,但是 binlog 还未写入就出现了 crash,这个时候,mysql 重启后,因为 redo log 未 commit,可以通过回滚将数据恢复。
  2. 如果在第二步发生 crash,也就是 redo log 为 prepare 状态,并且 binlog 已经写入,但是这时候出现了 crash,在 mysql 重启后,因为 binlog 已经有了记录,所以会继续提交该事务,否则 bin log 中数据新增了一条,而 redo log 没提交则可能发生两者数据不一致的情况。

# 相关链接