LVM快照可实现MySQL秒级物理备份,但需先执行FLUSH TABLES WITH READ LOCK、FLUSH LOGS、FLUSH ENGINE LOGS并记录binlog位置,再创建快照;xfs快照挂载前须运行xfs_repair -o force_geometry,ext4可直接只读挂载;恢复时必须删除ib_logfile*并核对innodb_log_file_size。

MySQL直接停机备份太慢?用LVM快照能秒级冻结数据文件
只要你的MySQL数据目录在LVM逻辑卷上,且文件系统是ext4/xfs这类支持快照的类型,LVM快照就是最轻量、最可靠的物理层备份手段。它不依赖MySQL自身状态,也不需要锁表或停服务——但必须确保mysqld进程已刷完所有脏页到磁盘,否则快照里可能含不一致的InnoDB页。
常见错误现象:ERROR 2013 (HY000): Lost connection to MySQL server during query 或备份后恢复时报InnoDB: Database page corruption,基本都是没等FLUSH TABLES WITH READ LOCK和FLUSH LOGS完成就建了快照。
- 先执行
FLUSH TABLES WITH READ LOCK(仅对MyISAM有效)+FLUSH LOGS(强制滚动binlog、刷redo),再立刻执行FLUSH ENGINE LOGS(InnoDB专用,确保redo日志落盘) - 用
SHOW MASTER STATUS记录当前binlog位置,后续恢复时要用到 - 快照创建命令必须在
FLUSH之后、UNLOCK TABLES之前执行,例如:lvcreate -L 5G -s -n mysql_snap /dev/vg0/mysql_data - 快照卷创建后立即
UNLOCK TABLES,让MySQL恢复正常写入
LVM快照挂载后发现文件系统只读或无法识别
这是xfs和ext4对快照处理方式不同导致的。xfs要求挂载前必须运行xfs_repair -o force_geometry(即使没报错也要跑),而ext4一般可直接mount -o ro挂载只读快照卷;若提示mount: wrong fs type,大概率是快照卷未激活或LV状态为suspended。
- 检查快照状态:
lvs -o +attr,origin,确认Attr列第5位是s(snapshot),且不是S(suspended) - 如被suspend,用
lvchange -ay /dev/vg0/mysql_snap激活 - xfs快照挂载前必做:
xfs_repair -o force_geometry /dev/vg0/mysql_snap(注意:该操作不修改原卷,只修复快照卷元数据) - 挂载命令统一用只读:
mount -o ro,nouuid /dev/vg0/mysql_snap /mnt/snap(nouuid防止与原卷UUID冲突)
备份文件拷贝慢、占用空间大?快照本身不压缩,但可以边挂载边rsync
LVM快照只是COW(写时复制)索引,实际数据块仍指向原LV,所以快照卷本身很小(初始几MB),但随着原卷写入增多,快照占用空间会线性增长。真正占空间的是你把整个/mnt/snap拷出去的过程——这不是快照的问题,而是备份策略问题。
- 不要
cp -r整个挂载点,改用rsync -a --delete --exclude='ib_logfile*' /mnt/snap/ /backup/mysql_$(date +%F)/ - 跳过
ib_logfile*和mysql-bin.*(这些在快照时刻已无效,应从SHOW MASTER STATUS记录的位置重放) - 如果网络传输慢,可在挂载后直接用
tar -cf - -C /mnt/snap . | gzip -c > backup.tar.gz,避免中间落盘 - 快照生命周期要短:备份完成后立刻
umount /mnt/snap && lvremove -f /dev/vg0/mysql_snap,否则原LV写入频繁时快照卷可能因空间耗尽而自动丢弃
恢复时MySQL启动失败,报InnoDB redo日志不匹配
这是最容易被忽略的一环:LVM快照备份的是某一瞬间的文件系统状态,但InnoDB重启时会尝试用redo日志前滚。如果快照里包含未完全刷盘的redo,或者你误把旧的ib_logfile*一起恢复了,MySQL就会拒绝启动。
- 恢复前务必清空目标数据目录下的
ib_logfile*和ibdata1(如果是独立表空间模式,ibdata1可保留,但ib_logfile*必须删) - 恢复命令示例:
rsync -a --delete /backup/mysql_2024-06-01/ /var/lib/mysql/,然后手动删除/var/lib/mysql/ib_logfile* - 启动前检查
my.cnf中innodb_log_file_size是否与备份时一致,不一致会导致启动失败 - 首次启动加
--innodb-force-recovery=1测试能否读取,成功后再去掉参数正常启
快照本身没问题,问题永远出在“以为文件全拷过去就能跑”这个想法上——InnoDB不是纯文件系统,它的崩溃恢复机制和redo生命周期必须被显式尊重。










