• 图解 MySQL 日志体系:让你明明白白记住各种 Log

图解 MySQL 日志体系:让你明明白白记住各种 Log

2025-06-19 10:00:06 栏目:宝塔面板 101 阅读

面试官:MySQL的日志系统了解吗?

我:MySQL有binlog、redo log...

面试官:那它们分别解决什么问题?为什么需要这么多种日志?

我:这个...(尴尬)

相信这样的对话很多同学都经历过。大家都知道MySQL有各种日志,但要说清楚它们的作用和关系,往往就不那么容易了。

作为一名有着7年MySQL开发经验的老兵,今天我用最通俗的语言,帮你彻底理解MySQL日志体系。

一、为什么MySQL需要日志系统?

让我们从一个最基础的数据库操作说起:

// 用户消费100元
UPDATE account SET balance = balance - 100 WHERE id = 1;

这条简单的SQL语句,实际上给数据库带来了三大挑战:

  • 可靠性问题:如果数据库突然宕机,这笔交易记录会不会丢失?
  • 一致性问题:如果用户要求退款,如何安全地回滚这笔交易?
  • 同步问题:如何确保其他数据库节点也正确记录了这笔交易?

为解决这些问题,MySQL设计了三种核心日志:

数据库操作 ──────────────────┐
                            ↓
┌─── Redo Log(临时记事本)
│     记录:"账户1减少100元"
│     作用:确保交易记录不丢失
│
├─── Undo Log(原始凭证)
│     记录:"账户1原有500元"
│     作用:随时可以撤销交易
│
└─── Binlog(总账本)
      记录:"完整交易记录"
      作用:用于数据同步和备份

二、重做日志(Redo Log):数据库的"草稿纸"

1. 场景:会计小徐的烦恼

超市收银员小徐要记录1000笔交易。

传统方式(没有Redo Log):

-- 每笔交易都要立即写入硬盘
UPDATE accounts SET balance = balance + 100;
UPDATE products SET stock = stock - 1;

结果:
┌─────────────────────┐
│ ❌ 频繁随机写入硬盘  │
│ ❌ I/O效率极低      │
│ ❌ 系统性能下降     │
└─────────────────────┘

Redo Log的解决方案:

1. 先写入速记本(Redo Log)
   ┌────────────────────┐
   │ 交易1: +100元,-1件 │ 
   │ 交易2: +200元,-2件 │ ➜ 顺序写入,速度快
   │ ...               │
   └────────────────────┘

2. 数据先放内存
   ┌────────────────┐
   │ 内存中快速汇总  │ ➜ 响应迅速
   └────────────────┘

3. 定期整理同步
   ┌────────────────┐
   │ 批量写入硬盘    │ ➜ 提高效率
   └────────────────┘

2. Redo Log工作原理详解

以顾客购买2箱牛奶为例:

// 顾客买了2箱牛奶(每箱100元)
UPDATE accounts SET balance = balance + 200;
UPDATE stock SET quantity = quantity - 2;

步骤1:速记本记录(Redo Log)

在Redo Log中记录交易信息:

交易编号

时间

操作类型

表名

修改内容

状态

001

09:01:01

UPDATE

accounts

账户余额+200

已记录

002

09:01:01

UPDATE

stock

牛奶库存-2

已记录

特点:

  • 顺序写入:像流水账,效率高
  • 记录简单:快速记录交易信息

步骤2:临时汇总(内存)

在内存中快速更新数据:

账户

余额

现金

1200

商品

库存数量

牛奶

98

特点:

  • 快速更新:客户立即看到结果
  • 数据在内存中:但断电会丢失

步骤3:持久化阶段,定期刷盘

在以下时机将数据写入硬盘:

  • 营业员交接班时
  • 系统空闲时
  • 速记本快写满时
  • 固定时间间隔

Redo Log 工作流程图:

三、回滚日志(Undo Log):数据库的"后悔药"

1. 场景:超市的退货处理

传统退货方式(没有Undo Log):

顾客:我要退刚买的牛奶 

小徐:抱歉,我们没记录原价,不知道该退多少钱...

现代方式(使用Undo Log)

顾客:我要退刚买的牛奶 

小徐:好的,让我查看下交易记录

  • 找到原始购买记录
  • 确认购买价格是100元
  • 确认库存状态
  • 可以安全退货

2. Undo Log 工作原理详解

场景:用户下单扣款

// 顾客购买2箱牛奶
UPDATE accounts SET balance = balance + 200;  // 收款200元
UPDATE stock SET quantity = quantity - 2;    // 库存减2

交易记录阶段(Undo Log记录)

编号

时间

表名

修改前数据

修改后数据

回滚指针

T001

09:01:01

accounts

balance=1000

balance=1200

-> T000

T002

09:01:01

stock

quantity=100

quantity=98

-> T001

T003

09:05:30

accounts

balance=1200

balance=1000

-> T002

T004

09:05:30

stock

quantity=98

quantity=100

-> T003

数据版本链(MVCC实现):

牛奶库存记录的版本链:
+-------------------------+
| 当前版本:98箱          | 
| 交易号:T002           |
+-------------------------+
          ↓
+-------------------------+
| 上一版本:100箱         |
| 交易号:T001           | 
+-------------------------+
          ↓
+-------------------------+
| 初始版本:100箱         |
| 交易号:T000           |
+-------------------------+

Undo Log 工作流程图:

3. Undo Log的两大作用

(1) 支持事务回滚

  • 记录数据修改前的状态
  • 支持出错时回滚
  • 保证事务原子性

(2) 实现MVCC(多版本并发控制)

  • 不同事务看到不同版本的数据
  • 提高并发性能
  • 避免加锁带来的性能问题

四、二进制日志(binlog):数据库的"保险箱"

1. 场景:连锁超市的账务管理

小徐是连锁超市的总经理,每天要处理这些数据管理问题:

场景一:商品管理
总店:上架100种新商品
┌─────────────────┐
│ 商品1: 牛奶     │
│ 商品2: 面包     │ ➜ 分店:一个个手动添加?
│ ...100条记录... │
└─────────────────┘

场景二:数据安全
┌─────────────────┐
│ 昨日销售数据    │ ➜ 系统崩溃,数据丢失!
└─────────────────┘

场景三:变更追踪
老板:这个商品谁改的价格?
小徐:¯_(ツ)_/¯ 不知道...

而有了Binlog(二进制日志)后:

MySQL Binlog
├── 自动同步
│   总店改价格 ──➜ 所有分店秒级更新
│
├── 数据保护
│   系统崩溃 ──➜ 从日志恢复数据
│
└── 操作追踪
    谁改了价格?──➜ 查看变更历史

2. Binlog的记录格式:如何记录数据变更?

让我们看看Binlog是如何记录数据变更的:

-- 一笔简单的商品价格调整
UPDATE products SET price = 98 WHERE name = '牛奶';

这条SQL语句在Binlog中有三种不同的记录方式:

(1) STATEMENT格式:记录SQL语句

# 直接记录SQL
UPDATE products SET price = price * 0.9 
WHERE category = '饮品';

优势:日志量小
风险:可能导致主从不一致(比如NOW()函数)

(2) ROW格式:记录数据变化

{
  "before": {"id": 1, "name": "牛奶", "price": 100},
  "after":  {"id": 1, "name": "牛奶", "price": 90}
}

优势:数据准确
特点:日志量较大

(3) MIXED格式:智能选择

# 根据SQL类型自动选择格式
简单UPDATE:使用STATEMENT
复杂函数:使用ROW

五、三大日志协同工作机制

以顾客购买2箱牛奶为例,操作内容如下:

  • 更新库存(-2箱)
  • 更新账户(+200元)

1. 两阶段提交工作流程

(1) 第一阶段(Prepare):

记录原始数据(Undo Log):

  • 库存:100箱
  • 账户:1000元

更新内存数据:

  • 库存:98箱
  • 账户:1200元

记录操作状态(Redo Log):

  • 状态:准备中
  • 内容:库存-2,账户+200

(2) 第二阶段(Commit):

记录交易信息(Binlog):

  • 时间:2025-04-14 09:00:00
  • 操作:售出牛奶2箱,收款200元

标记操作完成(Redo Log):

  • 状态:已完成

详细的执行流程表:

步骤

操作

日志类型

内容

状态

1

记录原数据

Undo Log

库存=100,余额=1000

已记录

2

更新内存

Buffer Pool

库存=98,余额=1200

已更新

3

预提交

Redo Log

更新操作记录

prepare

4

记录变更

Binlog

交易详细信息

已写入

5

最终提交

Redo Log

更新操作记录

commit

两阶段提交流程图:

六、总结

通过本文,我们深入了解了MySQL日志系统的核心内容:

三大日志的作用与原理:

  • Redo Log:确保数据持久性,像草稿纸,记录每一步操作。
  • Undo Log:支持事务回滚,类似价格标签,随时可以撤销错误。
  • Binlog:用于数据复制和恢复,犹如记账本,记录所有交易历史。

在数据库的世界里,日志不仅是记录,更是保障数据安全与一致性的基石。希望这些内容能帮助你更深入地理解MySQL日志系统的关键作用!


本文地址:https://www.yitenyun.com/297.html

搜索文章

Tags

数据库 API FastAPI Calcite 电商系统 MySQL Web 应用 异步数据库 数据同步 ACK 双主架构 循环复制 TIME_WAIT 运维 负载均衡 JumpServer SSL 堡垒机 跳板机 HTTPS 服务器 管理口 HexHub Docker 服务器性能 JumpServer安装 堡垒机安装 Linux安装JumpServer Deepseek 宝塔面板 Linux宝塔 SQL 查询 生命周期 esxi esxi6 root密码不对 无法登录 web无法登录 序列 核心机制 锁机制 Windows Windows server net3.5 .NET 安装出错 HTTPS加密 行业 趋势 Windows宝塔 Mysql重置密码 开源 PostgreSQL 存储引擎 宝塔面板打不开 宝塔面板无法访问 查看硬件 Linux查看硬件 Linux查看CPU Linux查看内存 机器学习 Redis Oracle 处理机制 Undo Log 机制 无法访问宝塔面板 Spring 动态查询 InnoDB 数据库锁 连接控制 优化 万能公式 监控 响应模型 Serverless 无服务器 语言 异步化 ES 协同 openHalo group by 索引 Postgres OTel Iceberg 工具 技术 高可用 分页查询 缓存方案 缓存架构 缓存穿透 scp Linux的scp怎么用 scp上传 scp下载 scp命令 SVM Embedding 存储 GreatSQL 连接数 数据 主库 国产数据库 R edis 线程 Linux 安全 SQLite-Web SQLite 数据库管理工具 日志文件 MIXED 3 R2DBC 加密 场景 Netstat Linux 服务器 端口 启动故障 ​Redis 推荐模型 Recursive 防火墙 黑客 云原生 OB 单机版 RocketMQ 长轮询 配置 自定义序列化 向量数据库 大模型 共享锁 SQLark AI 助手 Hash 字段 Canal PG DBA 信息化 智能运维 不宕机 Rsync 磁盘架构 Python 向量库 Milvus Ftp 分库 分表 架构 IT运维 电商 系统 数据分类 同城 双活 传统数据库 向量化 修改DNS Centos7如何修改DNS 业务 redo log 重做日志 语句 流量 聚簇 非聚簇 频繁 Codis 线上 库存 预扣 filelock MySQL 9.3 • 索引 • 数据库 MVCC MongoDB MCP 开放协议 缓存 sftp 服务器 参数 PostGIS mini-redis INCR指令 人工智能 推荐系统 数据类型 数据结构 Redisson 锁芯 失效 Doris SeaTunnel Web 接口 开发 千万级 大表 高效统计 今天这篇文章就跟大家 工具链 prometheus Alert 数据备份 分布式架构 分布式锁​ 窗口 函数 ZODB INSERT 聚簇索引 非聚簇索引 虚拟服务器 虚拟机 内存 COMPACT EasyExcel MySQL8 主从复制 代理 事务 Java 发件箱模式 分页 SSH 容器 崖山 新版本 引擎 性能 网络架构 网络配置 Web 数据脱敏 加密算法 核心架构 订阅机制 QPS 高并发 RDB AOF 数据集成工具 速度 服务器中毒 网络故障 B+Tree ID 字段 分布式 集中式 数据页 Go 数据库迁移 Redis 8.0 MGR 分布式集群 读写 Redka 容器化 播客 模型 OAuth2 Token 微软 SQL Server AI功能 自动重启 SpringAI Entity StarRocks 数据仓库 Caffeine CP 原子性 排行榜 排序 池化技术 连接池 Valkey Valkey8.0 DBMS 管理系统 JOIN LRU 关系数据库 事务隔离 网络 部署 Weaviate 业务场景 dbt 数据转换工具 分页方案 排版 Testcloud 云端自动化 数据字典 兼容性 Pottery 事务同步 1 ReadView 意向锁 记录锁 AIOPS sqlmock 日志 悲观锁 乐观锁 优化器 单点故障 Pump 单线程 UUIDv7 主键 仪表盘 UUID ID InfluxDB Order RAG HelixDB 对象 编程 Crash 代码 Ansible 分布式锁 Zookeeper 字典 双引擎 产业链 IT 订单 恢复数据 LLM List 类型 拦截器 动态代理 线程安全 国产 用户 慢SQL优化 表空间 快照读 当前读 视图 count(*) count(主键) 行数 解锁 调优 RR 互联网 Next-Key GitHub Git 神经系统 矢量存储 数据库类型 AI代理 查询规划 CAS 技巧 算法 多线程 闪回 并发控制 恢复机制