社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

MySQL的三大日志

码小辫 • 4 天前 • 22 次点击  


码小辫 丝认证

点击关注后,你不仅获得一个找资源的工具,更获得一个有趣的灵魂  ▶  ▶  ▶




前言

飞机失事靠黑匣子还原真相,MySQL崩溃靠三大日志保障数据安全。

作为一个工作多年的程序员,我见过太多因日志配置不当引发的灾难:数据丢失、主从同步中断、事务回滚失败...

今天,我将用最通俗的方式,带你彻底掌握MySQL三大日志的底层原理,希望对你会有所帮助。

一、引子:一个数据丢失的教训

事故现场:某电商平台数据库服务器宕机后,发现最近2小时订单数据丢失。

问题根源:  错误配置导致redo log刷盘失效:


SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 0     |  -- 应设为1
+--------------------------------+-------+

核心结论

  1. 日志系统是MySQL的安全气囊
  2. 不理解日志机制,等于在数据安全上裸奔

二、Redo Log:保证持久性的守护神

2.1 核心作用:崩溃恢复

WAL原则(Write-Ahead Logging)

2.2 物理结构解析

循环写入机制

关键参数




    
-- 查看日志配置
SHOW VARIABLES LIKE 'innodb_log%';
+---------------------------+---------+
| Variable_name             | Value   |
+---------------------------+---------+
| innodb_log_file_size      | 50331648| -- 单个日志文件大小
| innodb_log_files_in_group | 2       | -- 日志文件数量
| innodb_log_buffer_size    | 16777216| -- 缓冲区大小
+---------------------------+---------+

2.3 刷盘策略实战

// JDBC事务提交示例
Connection conn = DriverManager.getConnection(url, user, pwd);
try {
    conn.setAutoCommit(false);
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("UPDATE account SET balance=balance-100 WHERE id=1");
    stmt.executeUpdate("UPDATE account SET balance=balance+100 WHERE id=2");
    
    // 核心配置:刷盘策略
    conn.setClientInfo("innodb_flush_log_at_trx_commit""1");
    conn.commit(); // 触发redo log刷盘
catch (SQLException e) {
    conn.rollback();
}

刷盘策略对比

参数值
安全性
性能
适用场景
0
低(每秒刷)
最高
可丢失数据的缓存
1
最高(实时)
最低
金融交易系统
2
中(OS缓存)
较高
常规业务系统

三、Undo Log:事务回滚的时光机

3.1 MVCC实现原理

多版本控制流程

3.2 回滚操作源码级解析

-- 事务回滚示例
START TRANSACTION;
UPDATE users SET name='张三' WHERE id=1
-- 在undo log中记录:
-- | 事务ID | 行ID | 旧值 | 回滚指针 |
-- | 101    | 1    | '李四'| 0x7F8A9B|

ROLLBACK-- 根据undo log恢复数据

3.3 长事务引发的灾难

问题场景

-- 查询运行超过60秒的事务
SELECT  * FROM information_schema.innodb_trx 
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;

严重后果

  1. Undo Log暴涨占用磁盘空间
  2. 历史版本链过长导致查询性能下降

解决方案

@Transactional(timeout = 30// 单位:秒
public void updateOrder(Order order) {
    // 业务逻辑
}

Spring Boot项目可以设置事务超时时间。

四、Binlog:主从复制的桥梁

4.1 三种格式深度对比

格式
特点
数据安全
复制效率
STATEMENT
记录SQL语句
ROW
记录行变化
MIXED
自动切换模式

ROW格式的优势

-- 原始SQL
UPDATE users SET status=1 WHERE age>30;

-- ROW格式binlog实际记录
/* 修改前镜像 */
id:1, status:0, age:35
id:2, status:0, age:40
/* 修改后镜像 */
id:1, status:1, age:35
id:2, status:1, age:40

4.2 主从复制全流程剖析

4.3 数据恢复实战

场景:误删全表数据
恢复步骤

# 1. 解析binlog找到删除位置
mysqlbinlog --start-position=763 --stop-position=941 binlog.000001 > recovery.sql

# 2. 提取回滚SQL
grep -i 'DELETE FROM users' recovery.sql

# 3. 生成反向补偿语句
sed 's/DELETE FROM/INSERT INTO/g' recovery.sql > rollback.sql

# 4. 执行恢复
mysql -u root -p < rollback.sql

五、三大日志协同工作图

更新语句执行流程

两阶段提交关键点

  1. redo log prepare 与 binlog 写入的原子性
  2. 崩溃恢复时的决策逻辑:
  • binlog完整:提交事务
  • binlog不完整:回滚事务

六、生产环境优化指南

6.1 参数调优模板

my.cnf 关键配置:

[mysqld]
# Redo Log
innodb_log_file_size = 2G        # 建议4个日志文件
innodb_log_files_in_group = 4
innodb_flush_log_at_trx_commit = 1

# Undo Log
innodb_max_undo_log_size = 1G
innodb_undo_log_truncate = ON
innodb_purge_threads = 4

# Binlog
server_id = 1
log_bin = /data/mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800 # 保留7天
sync_binlog = 1                   # 每次提交刷盘

6.2 监控指标清单

-- 关键监控SQL
SELECT
/* Redo Log */
  (SELECT VARIABLE_VALUE 
   FROM performance_schema.global_status 
   WHERE VARIABLE_NAME='Innodb_os_log_written'AS redo_written,
   
/* Undo Log */
  (SELECTSUM(DATA_LENGTH) 
   FROM information_schema.TABLES 
   WHERE TABLE_SCHEMA='mysql'
   AND TABLE_NAME LIKE'undo%'AS undo_size,
   
/* Binlog */
  (SELECT VARIABLE_VALUE 
   FROM performance_schema.global_status 
   WHERE VARIABLE_NAME='Binlog_cache_disk_use'AS binlog_disk_use;

6.3 常见问题解决方案

问题1:redo log文件设置过小导致频繁checkpoint。

现象

SHOW GLOBAL STATUS LIKE 'Innodb_log_waits';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_log_waits | 542   | -- 值>0表示存在等待
+------------------+-------+

解决

# 动态调整(需重启生效)
SET GLOBAL innodb_log_file_size = 2147483648

问题2:大事务导致binlog暴涨。

预防方案

// 事务拆分示例
public void batchProcess(List orders) {
    int batchSize = 100// 每100条一个事务
    for (int i=0; i
        transactionTemplate.execute(status -> {
            List subList = orders.subList(i, Math.min(i+batchSize, orders.size()));
            processBatch(subList);
            return null;
        });
    }
}

七、总结

  1. Redo Log是生命线

  • 配置原则:innodb_flush_log_at_trx_commit=1 + 足够大的日志文件
  • 监控重点:Innodb_log_waits 应趋近于0
  • Undo Log是后悔药

    • 及时清理:开启 innodb_undo_log_truncate
    • 避免长事务:监控 information_schema.innodb_trx
  • Binlog是复制基石

    • 格式选择:金融级系统必须用ROW格式
    • 同步策略:主从复制时 sync_binlog=1

    数据库的可靠性不是偶然发生的,而是通过三大日志的精密协作实现的。

    当你下次执行COMMIT时,请记住背后有三个强大的守护者在为你工作:

    1. Redo Log确保你的数据不会丢失
    2. Undo Log保证你的操作可以撤销
    3. Binlog让数据在集群间流动

    敬畏日志,就是敬畏数据安全!


    高质量原创回顾


    中国最难入职的IT公司...


    马斯克发私信让美女网红给他生娃,被拒以后切断了网红每两周2.1万美元广告收入?


    外包同事参加聚餐,刚到包间门口,就听主管说:都自己人,以后有啥脏活累活都给外包,他们本就是服务咱的,不要不好意思


    离职交接后,线上出现bug,接口是自己开发的,n+1补偿被追回了


    听说互联网不卡35岁了?


    程序员为保饭碗,开始“防御性编程”.....


    字节这波操作,直接改变了大家的习惯?


    华为员工爆料:OD大部分人是入职即巅峰!D4级,除了升D5时月薪涨了3k,其他时候从来没涨过

    图片


    别忘了点分享、收藏、在看、点赞哦!


    图片


    Python社区是高质量的Python/Django开发社区
    本文地址:http://www.python88.com/topic/184573
     
    22 次点击