数据库备份最佳实践:从mysqldump锁表故障说起

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
云数据库 PolarDB MySQL 版,列存表分析加速 8核16GB
RDS Agent(兼容OpenClaw),2核4GB
简介: 从一次凌晨3点的真实故障出发,拆解mysqldump锁表引发主从延迟和应用超时的完整链路,附七步排查法、xtrabackup替代方案与生产环境调参建议

大家好,我是数据库小学妹 👋

上周凌晨3点,被一通电话吵醒。运维说从库CPU飙了,应用在超时,让我赶紧看看。

我爬起来打开电脑,迷迷糊糊登录服务器,top一看——mysqldump。

当时心里就咯噔一下,备份怎么会搞出这么大动静?

排查下来才发现,事情一环扣一环:备份锁表,主从延迟飙升,应用跟着超时。从3点05分告警到3点52分恢复,整整47分钟,我那天基本没怎么睡。

今天把这次排查过程整理出来。

故障现场

告警群在3点05分炸的,消息一条接一条。从库CPU 100%,主从延迟从0飙到300秒,应用开始报超时。

我登录从库服务器,top一看,mysqldump进程CPU占用80%多,IO也在高位。再看从库状态:

SHOW SLAVE STATUS

Seconds_Behind_Master已经300多了,而且还在涨。

备份为什么会锁表

mysqldump备份时会执行FLUSH TABLES WITH READ LOCK(FTWRL),获取全局读锁。这个锁会阻塞所有写操作。

为什么mysqldump要加这个锁?因为它需要拿到一个一致性位点(consistent snapshot)。备份过程中如果有写操作,备份出来的数据就不一致了——比如你备份到一半,某个表被truncate了,备份出来的数据就缺了一块。

FTWRL的执行分三步:

  1. Close tables — 关闭所有已打开的表,把脏页刷到磁盘。这一步会等所有正在执行的语句结束
  2. Acquire global read lock — 拿到全局读锁,之后所有写操作被阻塞
  3. Get binlog position — 记录当前binlog位点,作为一致性快照的参照

问题就出在第一步。如果有大查询在跑,比如一个跑了20分钟的报表JOIN,Close tables会一直等它结束。关键是,这期间FTWRL已经开始阻塞新的写操作了——锁已经在排队,但还没拿到,新的写请求全卡在那。

更坑的是,如果你用的是MyISAM引擎,--single-transaction参数根本没用。这个参数只对InnoDB生效,通过开启一个一致性读事务来避免FTWRL。MyISAM没有事务机制,只能老老实实加全局锁。

我那个场景,从库上有个报表查询在跑,执行了20多分钟。FTWRL等这个查询结束,期间所有写操作都卡住了。

备份锁表为什么会影响主库

备份锁表影响的是从库,但为什么会波及主库?这个问题当时我也想了好一会。

主从复制的基本流程:主库执行写操作 → 写入binlog → 从库IO线程拉取binlog → 从库SQL线程回放。从库锁表后,回放被阻塞,binlog在从库这边就堆积起来了。

半同步复制下问题更严重。 如果你配置了半同步复制(semi-sync replication),主库提交事务后要等至少一个从库确认收到binlog才返回客户端。从库锁表导致回放卡住,binlog确认也卡住,主库的写操作直接被拖慢。我遇到的场景就是半同步,主库的TPS从3000掉到了个位数。

binlog堆积会撑爆磁盘。 主库的binlog要等从库确认接收后才能清理。从库一直不确认,主库的binlog就一直涨。我遇到过一次,binlog涨了50多G,磁盘直接告警。如果你配了expire_logs_days,MySQL会尝试清理过期binlog,但如果还有从库没读完,它不敢删,磁盘空间就这么被撑满。

并行复制场景下影响更大。 如果从库开了MTS(Multi-Threaded Slave),多个worker线程并行回放binlog。FTWRL一锁,所有worker线程全卡住,延迟蹭蹭往上涨。我见过延迟从0飙到3000秒的,就是因为MTS的协调线程在等全局锁。

还有个容易忽略的点:从库延迟变大,如果有读写分离配置,应用读到的是旧数据。用户下单成功,刷新页面发现订单没出来,投诉就来了。

应用为什么会超时

从库锁表、主从延迟,应用为什么会超时?

如果应用配置了读写分离,读请求会发到从库。从库锁表后,读请求被阻塞,等待锁释放。

应用有超时设置,比如30秒。从库锁表时间超过30秒,应用就报超时。

超时后应用可能会重试,重试又打到从库,又被阻塞。大量请求堆积,连接池被耗尽,应用开始报"连接池已满"。

我那个场景,应用配置了3次重试。每次重试都等30秒,一个请求就等90秒。并发一上来,连接池很快就满了。

排查过程

排查这个故障用了大概20分钟。说实话,刚看到CPU 100%的时候,我第一反应是磁盘满了或者内存泄漏,完全没想到是备份的锅。

第一步:看系统资源,排除硬件问题。

top -c
iostat -x 1 3
df -h

top一看,mysqldump进程CPU占用80%多。iostat的%util也在高位,说明IO也在打满。磁盘空间还有余量,排除磁盘满的可能。

到这一步我基本确认是mysqldump的问题了,但还得往下查影响面。

第二步:看从库复制状态,确认延迟程度。

SHOW SLAVE STATUS\G

重点看这几个字段:

Seconds_Behind_Master: 347
Slave_SQL_Running: Yes
Slave_IO_Running: Yes
Last_Error: (空)

SQL线程和IO线程都在跑,没有报错,说明不是复制本身出了问题,而是回放被阻塞了。Seconds_Behind_Master 347秒,而且还在涨,这个延迟量级不是小问题。当时心里就凉了半截。

第三步:看从库进程,找阻塞原因。

SHOW PROCESSLIST;

输出里看到大量这样的状态:

State: Waiting for table flush

我愣了一下——等了几秒才反应过来,这是FTWRL的特征。说明有全局读锁在排队。

第四步:找备份进程,确认根因。

ps aux | grep mysqldump

果然,凌晨3点的定时备份任务在跑。命令大概是:

mysqldump --all-databases --master-data=2 > /data/backup/full.sql

注意这里没加--single-transaction,所以会走FTWRL。

第五步:确认锁的范围。

SHOW OPEN TABLES WHERE In_use > 0;
SELECT * FROM performance_schema.metadata_locks
WHERE OBJECT_TYPE = 'GLOBAL';

SHOW OPEN TABLES可以看到哪些表被锁了。如果你用的是MySQL 5.7+,performance_schema.metadata_locks能更精确地看到锁的类型和持有者。

第六步:评估主库影响。

SHOW BINARY LOGS;

binlog数量在涨,说明从库确认跟不上,主库的binlog清理不了。

SHOW GLOBAL STATUS LIKE 'Rpl_semi_sync_master_no_tx';

这个值在涨,说明半同步复制已经在退化成异步了——主库等不到从库确认,开始降级。

第七步:看应用日志,评估业务影响。

应用日志里大量Connection pool exhaustedQuery timeout。这里我走了一小段弯路——一开始以为是应用代码bug,查了半天才发现是从库锁表传导过来的。

定位到问题后,KILL了备份进程。主从延迟大概5分钟开始下降,应用在10分钟左右恢复正常。

解决方案

这次故障后,我做了几个改进。

用xtrabackup替代mysqldump

xtrabackup是Percona的物理备份工具,最大的优势是不需要FTWRL。它的工作原理分两个阶段:

备份阶段: 直接拷贝InnoDB的数据文件(.ibd),同时持续监听并拷贝redo log。因为拷贝的是物理文件,不需要锁表来保证一致性——后续的修改都记录在redo log里。整个过程只加一把轻量级的backup lock(MySQL 8.0是LOCK INSTANCE FOR BACKUP),不会阻塞DML操作。

Prepare阶段: 备份完成后,用redo log对数据文件做crash recovery,把备份期间的修改回放进去,得到一个一致性快照。这一步在备份结束后离线做,不影响线上业务。

# 备份
xtrabackup --backup --target-dir=/data/backup/ \
  --user=backup_user --password=xxx

# Prepare(应用redo log,保证一致性)
xtrabackup --prepare --target-dir=/data/backup/

还有一个容易被忽略的好处:xtrabackup支持增量备份。第一次全量备份后,后续只拷贝变化的数据页,备份速度快很多,对IO的影响也小。

# 增量备份(基于上次全量)
xtrabackup --backup --target-dir=/data/backup/inc1 \
  --incremental-basedir=/data/backup/full

如果只能用mysqldump怎么办

有些场景你可能没法装xtrabackup,那mysqldump也不是不能用,关键是要加对参数:

mysqldump --single-transaction --routines --triggers \
  --master-data=2 --flush-logs --all-databases > /data/backup/full.sql

--single-transaction会开启一个一致性读事务,对InnoDB表不需要FTWRL。但有两个前提条件:

  1. 备份期间不能有DDL操作(ALTER TABLE、CREATE INDEX等),DDL会隐式提交事务,破坏一致性
  2. MyISAM表还是会锁,如果你还有MyISAM表的话

备份窗口规划

备份时间避开业务高峰,晚上10点到凌晨2点是备份窗口,其他时间不备份。这个看起来简单,但很多团队的定时任务是随便写的,凌晨3点恰好是某些报表任务的高峰期。

建议在cron里用nice和ionice限流,避免备份打满IO:

nice -n 19 ionice -c2 -n7 xtrabackup --backup --target-dir=/data/backup/

这样备份进程的CPU和IO优先级都是最低的,不会抢占业务资源。

监控前置

在主从延迟超过10秒时就告警,而不是等到300秒。我后来用PMM(Percona Monitoring and Management)搭了一套监控,设了三级告警:

  • 延迟 > 10秒:钉钉通知
  • 延度 > 60秒:电话告警
  • 延迟 > 300秒:自动触发应急预案

另外备份进程也要监控。写个简单的脚本,备份开始和结束都打个时间戳到监控系统,如果备份超过预设时间(比如2小时)还没结束,也要告警。

长期架构改进

如果业务量继续增长,从库的压力会越来越大。几个方向可以考虑:

  1. 专用备份从库 — 单独起一个从库专门做备份,不承担业务读流量。备份延迟不影响业务
  2. 延迟从库 — 配置CHANGE MASTER TO MASTER_DELAY=N,故意延迟N小时。万一主库误删数据,可以从延迟从库捞回来
  3. 逻辑备份+物理备份结合 — 物理备份做全量恢复用,逻辑备份做跨版本迁移和单表恢复用,两种工具各有各的场景,别只备一种

避坑清单

  1. 能用xtrabackup就别用mysqldump,物理备份走redo log保证一致性,不需要全局锁。如果只能用mysqldump,一定加--single-transaction,但注意这个参数对MyISAM无效
  2. 备份前先SHOW PROCESSLIST看一眼从库有没有大查询在跑,我那次就是没检查,FTWRL卡了20多分钟才拿到锁。备份窗口也别随便定,凌晨3点看起来冷门,可能是报表高峰期
  3. 从库锁表会波及主库,尤其是半同步复制场景,主库TPS可能直接掉到个位数。主从架构一定要提前评估备份的影响面,业务量大的话建议搭专用备份从库,把备份压力和业务读流量隔离开

你们线上备份用的什么方案?有没有踩过类似的坑?评论区聊聊 👇

我是数据库小学妹,咱们下篇见 👋

相关文章
|
4天前
|
云安全 人工智能 运维
阿里云SecOps Agent,全新安全跨产品执行体验
自然语言驱动 云安全中心/WAF/CFW/ 等多款安全产品联动
1595 2
|
1天前
|
人工智能 定位技术 SEO
我学 GEO 第 15 天:终于知道AI GEO该如何做?
我是暴走的莉莉酱,边旅行边研究AI GEO的数字游民。专注普通人如何提升“AI可见度”——让AI在回答用户问题时准确识别、理解并推荐你。不讲玄学,只做可测、可调、可持续的GEO实践。
348 122
|
4天前
|
机器学习/深度学习 人工智能 调度
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
HappyHorse 1.1 是新一代视频生成大模型,全面升级动态表现力、角色一致性、指令遵循、视觉质感与音画协同能力。支持I2V/T2V/R2V三类生成,适配短剧、电商广告、品牌营销等场景,提供高质、流畅、可控的AI视频生产力。
577 3
🐴 HappyHorse 1.1 现已上线阿里云百炼!快来查收模型使用指南,现在调用享 6 折~
|
14天前
|
缓存 测试技术 API
Qwen 3.7 Plus 与 Max 实测:性价比与多模态能力差异解析(2026)
2026 年 6 月 1 日,阿里悄无声息地发布了 Qwen 3.7 Plus,距 Qwen 3.7 Max 上线刚好 11 天。同样的 1M 上下文,同样的 35 小时自治上限。但价格才是头条:Plus 是 0.40/M输入,Max是 2.50/M——便宜约 6 倍——并且还能看图、看视频。Vision Arena 上 Plus 已经排到 #16。所以这周真正值得讨论的问题不是”要不要为视觉能力买单”,而是”Max 凭什么用 6 倍价格换来 2 个百分点的 benchmark 领先”。
|
15天前
|
JavaScript 定位技术 API
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
CodeGraph 是一款爆火的本地代码智能工具,通过 tree-sitter 解析 AST 构建结构化知识图谱(存于 SQLite),为编程 Agent 提前生成“代码地图”。它显著降低 Agent 在中大型项目中的探索成本——实测工具调用减少71%、Token 降57%、速度提升46%,支持19+语言及主流框架路由识别,完全离线、无需 API Key。
910 11
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
|
8天前
|
缓存 人工智能 运维
GLM 5.2自托管全流程实战:硬件选型、vLLM/SGLang部署与成本盈亏测算
2026年智谱发布GLM 5.2超大混合专家模型,区别于以往仅开放API的闭源大模型,该模型权重以MIT开源协议对外发布,企业与开发者可完整下载、本地审计、私有化部署,实现数据不出环境、自定义微调、自主调度推理资源。GLM 5.2拥有753B总参数,原生支持百万级上下文窗口,在代码生成、长文档推理、数学逻辑等多项基准测试中对标国际顶尖商用模型,是首款可完整自托管的前沿代码向大模型。
651 0
|
2天前
|
消息中间件 人工智能 Kafka
AI 时代,实时入湖正在告别 ETL:从 Kafka 到 Iceberg 的架构减法
本文围绕“零 ETL”这一趋势,讨论流数据入湖为什么需要做架构减法,并结合 Kafka × Table Bucket 的实践,分析一种将通用入湖能力前移到消息与表存储链路中的方案,如何在降低复杂度的同时,兼顾实时性、一致性、Schema 演进、CDC 语义与开放生态兼容。
192 121
|
2天前
|
人工智能 监控 前端开发
Electron 监控:让桌面 Agent 监控触手可及
一行代码实现Electron桌面端全景监控,自动还原崩溃现场、预警内存泄漏、全链路追踪、 SSE流式响应与交互埋点,让 AI 助手运行状态清晰可见,助力快速恢复稳定与流畅。
182 125
|
11天前
|
人工智能 自然语言处理 算法
阿里云百炼Qwen 3.7 Plus与Max实测全解:性价比与多模态能力、成本深度对比
2026年,阿里云百炼平台推出的Qwen 3.7系列成为企业与开发者落地AI应用的核心选择,其中Qwen 3.7 Max与Plus作为两大旗舰版本,定位差异显著:Max是纯文本推理旗舰,专注高强度智能体与复杂逻辑任务;Plus则是多模态全能版,在保留强大文本能力的同时,补齐图像、视频理解能力,且价格大幅降低。本文基于2026年最新实测数据,从核心参数、文本能力、多模态能力、智能体表现、性价比与场景选型六大维度,全面解析两款模型的差异,为用户提供精准选型参考。
537 0