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

推荐订阅源

V
V2EX
IT之家
IT之家
博客园 - 叶小钗
雷峰网
雷峰网
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
爱范儿
爱范儿
博客园 - 【当耐特】
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
大猫的无限游戏
大猫的无限游戏
Last Week in AI
Last Week in AI
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
Jina AI
Jina AI
博客园 - Franky
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
阮一峰的网络日志
阮一峰的网络日志
Hugging Face - Blog
Hugging Face - Blog
博客园 - 司徒正美

博客园 - MSSQL123

timescaledb 扩展 PostgreSQL 18+ 版本下源码编译安装 ubuntu24下 ext4和xfs类型磁盘以及PostgreSQL实例性能对比测试 PostgreSQL 18 新特性 skip scan,一个鸡肋的功能 PostgreSQL 17 流复制中开启逻辑复制槽同步,以及逻辑槽的故障转移 记一次PostgreSQL交叉表crosstab行转列导致的OOM TiDB 扩容与缩容 PostgreSQL 高可用集群 patroni 自动故障转移测试 Ubuntu 20 环境下 patroni 自动化安装,一分钟快速搭建 patroni 集群 Ubuntu 20 环境下 pg_auto_failover 自动化安装,一分钟快速搭建pg_auto_failover集群 PostgreSQL的消息队列扩展pgmq 磁盘IO延迟和队列深度的关系 TiDB 最小拓扑架构集群安装 PostgreSQL 逻辑复制中的同步和异步模式以及其表现 prometheus 的 altermanager Silences静默告警,优雅地抑制告警 “世界上百分之99的博士和他们的论文都是垃圾”,原本以为这个观点偏激 pg_auto_failover 在多种场景下自动故障转移的验证 pgbouncer连接池设置与压力测试的最大连接数测试 pg_auto_failover 自动故障转移参数 博文阅读密码验证 - 博客园 pg_auto_failover 高可用中,PostgreSQL实例配置文件的加载步骤 pg_auto_failover集群monitor节点的高可用 prometheus监控Linux Server node_exporter代理安装和配置 prometheus监控windows window_exporter代理安装和配置 Prometheus 和 Grafana 监控 PostgreSQL SQLServer 2019 标准版在虚拟机上无法充分利用CPU的问题诊断 Windows Failover Cluster集群中的EventId 1196错误日志 pg_auto_failover 环境变量导致的show命令错误 SqlServer 事务复制(transaction replication)的复制位点信息 SqlServer 事务复制的两个参数immediate_sync,allow_anonymous MySQL,SqlServer,PostgreSQL中,如何实现锁定一张表
记一次MySQL binlog日志导致磁盘空间占满的问题
MSSQL123 · 2025-12-16 · via 博客园 - MSSQL123

背景

某开发人员反馈,一个MySQL测试环境的数据库服务器,磁盘空间被占满,并且明确告知MySQL数据库并不大,但是其binlog日志占用数百GB的空间,远远超出预期的大小,要协助检查为什么binlog会占用如此大的空间。
简言之就是:数据量较小,binlog的日志量很大。

binlog相关的配置信息

查看MySQL binlog相关的参数,
1,binlog_expire_logs_auto_purge是打开的,MySQL会自动清理过期的日志,这一点没有问题。
2,对于max_binlog_size为1G,binlog_expire_logs_seconds为30天,也就是单个binlog最大为1G,binlog保留时间为30天。

SELECT
  variable_name,
  variable_value
FROM performance_schema.global_variables
WHERE variable_name IN (
  'log_bin',
  'binlog_format',
  'max_binlog_size',
  'binlog_expire_logs_seconds',
  'binlog_expire_logs_auto_purge',
  'binlog_row_image',
  'binlog_row_metadata'
);


|variable_name                      |variable_value |
| binlog_expire_logs_auto_purge     | ON |
| binlog_expire_logs_seconds        | 2592000 |
| binlog_format                     | ROW |
| binlog_row_image                  | FULL |
| binlog_row_metadata               | MINIMAL |
| log_bin                           | ON |
| max_binlog_size                   | 1073741824 |

binlog文件查看

上面的参数可以知道,binlog自动清理选项打开了,那么就直接分析已有binlog的内容,这里先查看binlog文件信息,以及活动binlog中记录到的操作类型。

SHOW BINARY LOGS;
Log_name;File_size;Encrypted
……
binlog.000019;1073742747;No
binlog.000020;1073742747;No
binlog.000021;1073742747;No
binlog.000022;1073742747;No
binlog.000023;1073743263;No
binlog.000024;189129008;No


SHOW BINLOG EVENTS IN 'binlog.000024' LIMIT 10000;

从binlog中的Event类型可以看到,对于数据库中的某一张表,有大量的insert操作(write_rows)和delete操作(delete_rows)

image

show binlog events只能粗略看到binlog中的操作的表以及对应的操作类型,无法查看其详细的操作信息或者说对应的SQL语句,因此只能通过mysqlbinlog命令来解析出来binlog来查看其具体的SQL语句信息。

mysqlbinlog工具的使用

mysqlbinlog 是 MySQL 官方自带的二进制日志(binlog)解析与回放工具,主要用于查看、分析、恢复、重放 MySQL 的 binlog。
一句话总结:它可以把MySQL的二进制日志翻译成人能看懂的文本格式,用以分析二进制日志的内容;也能生成可执行的SQL用于回放二进制日志;还可以直接将binlog的内容直接重放,用以恢复数据库。
mysqlbinlog典型的用法用下:

mysqlbinlog --no-defaults --base64-output=decode-rows -vv binlog.000022 >binlog.000022.sql

--no-defaults
忽略所有默认配置文件,只使用命令行参数解析命令行中的binlog;或者实现离线解析当前的binlog

--database=xxx
数据库过滤,示例如下,增加database参数之后会给出一个警告,
mysqlbinlog --no-defaults --database=xxx--base64-output=decode-rows -v binlog.000024 >binlog.000024.sql
WARNING: The option --database has been used. It may filter parts of transactions, but will include the GTIDs in any case. If you want to exclude or include transactions, you should use the options --exclude-gtids or --include-gtids, respectively, instead.
--base64-output=decode-rows
目的是过滤掉二进制数据,
如果不加--base64-output=decode-rows,则翻译为类似于 BINLOG '459AaRMBAAAAPgAAAAgHAAAAAFMAAAAAAAEAA3R0ZAAHbG9nX2RwZQAEAw/8EgSHAAIAAAEBAAIB'的文本。这部分文本信息只是用以恢复数据库,并不适合于用户的查看,所以进查看日志的时候,可以过--base64-output=decode-rows过滤掉这部分信息。
需要注意的是:
如果只是想查看binlog中的SQL语句,可以加上--base64-output=decode-rows,
如果是想利用到处的sql文件恢复数据,那么一定不能指定--base64-output=decode-rows,因为加上--base64-output=decode-rows之后,不会解析出真正用于恢复数据的。

-vv(verbose)
显示具体的SQL语句,通常是-vv或者-vvv,-vvv是更加详细的SQL语句,绝大多数情况下用-vv就足够了。

position
用于指定具体的binlog位点信息来筛选部分binlog,除非binlog非常大,或者非常清楚相关数据的位点,增加此参数来过滤binlog的导出,一般不用该参数做筛选操作
--start-position=POS
--stop-position=POS

datetime

用于指定具体的binlog事务时间点信息来筛选部分binlog,除非binlog非常大,或者非常清楚相关数据的位点,增加此参数来过滤binlog的导出,一般不用该参数做筛选操作
--start-datetime="YYYY-MM-DD HH:MM:SS"
--stop-datetime="YYYY-MM-DD HH:MM:SS"

mysqlbinlog常用导出方式

1,mysqlbinlog --no-defaults  -vv binlog.000024 >binlog.000024.sql

该场景下,导出的sql文件格式参考如下,既不会破坏binlog的可恢复性,也能看到具体的SQL语句
image

2,mysqlbinlog --no-defaults --base64-output=decode-rows -v binlog.000022 >binlog.000022.sql
该场景下,通过--base64-output=decode-rows筛选掉二进制内容,内容更简洁,能看到具体的SQL语句,但是导出后的sql文件不可用于数据恢复操作。

image

mysqlbinlog分析binlog

由于只是分析binlog中的内容,而不是用以恢复数据库,因此才使用上述第二种方式导出相关的binlog成sql文件。


mysqlbinlog --no-defaults --base64-output=decode-rows -v binlog.000022 >binlog.000022.sql
结果上述show binlog event中显示的内容,发现有一个日志表,会频繁写入数据,每秒钟数百行,每天可达千万行,同事会在凌晨某个时间点通过MySQL的Event定时任务来删除最早的日志。
表面上看,整个数据库并不大,但是应用程序在写入数据的时候,会生成binlog,定时任务在删除数据的时候同样会生成大量的binlog,同时binlog的保留期限为30天,这样就会造成服务器上挤压大量的binlog,使得binlog占用的空间远远超出数据库自身的空间。

image

很多时候,可能会潜在一个误区,明明数据库并不大,为什么会产生大量的binlog,其实数据库本身记录的是存量数据,而binlog记录的是增删改操作本身,如果频繁第写入和删除,即便是存量数据并不大,但也会生成大量的binlog。

实际分析过程中,在上述命令的基础上,增加了管道过滤功能,仅导出相关的DDL语句,而忽略其他信息,从而简化日志量的大小和分析日志的干扰项
mysqlbinlog --no-defaults --base64-output=decode-rows -vv   binlog.000024 | grep -E "^### (INSERT|UPDATE|DELETE)" >binlog.000024.sql
image
最终到处的日志格式如下,得到一个非常简洁的信息,以便来做统计分析。
image

补充:利用binlog恢复数据库

附带利用binlog恢复数据库的两种可选方案,强烈建议使用方式1,也就是人工确认binlog的具体内容符合预期之后再恢复,尤其是生产环境。

基于binlog的数据恢复

###方案1:
1,完整备份恢复
2,在完整备份恢复的基础上,利用将binlog导出为sql文件,人工确认数据范围是否符合预期,然后再进行恢复
-- binlog 导出sql
mysqlbinlog --no-defaults -vv --start-datetime="2025-12-15 00:00:00"  --stop-datetime="2025-12-15 07:05:40" binlog.000022 >binlog.000022.sql

--登录MySQL后,用source命令,从sql文件中恢复
mysql -u root -p -h 127.0.0.1 -P 3307
source /usr/local/binlog.000022.sql



###方案2:
1,完整备份恢复
2,在完整备份恢复的基础上,利用binlog进行回复
mysqlbinlog --no-defaults  --start-datetime="2025-12-15 00:00:00"  --stop-datetime="2025-12-15 07:05:40"    --skip-gtids --disable-log-bin binlog.000022 | mysql -uroot -p