MySQL进阶12 — 备份与恢复

概述

本章,您将学习 MySQL 当中关于备份与恢复的内容,内容包括:

  • 基本概念
  • MySQL 自带的逻辑备份与逻辑恢复
  • 第三方物理备份工具

基本概念

从表空间的概念可知:

表空间是逻辑层与物理层的中间桥梁,它是用户逻辑对象(表、索引等)的存储空间,用来统一管理空间中的数据文件。

因此在备份数据时,就需要围绕逻辑层与物理层来实现。

  • 逻辑备份 - 以具体的 SQL 语句进行备份保存,备份文件的内容可允许文本格式,也允许二进制格式。

  • 逻辑恢复 - 解析备份文件的内容进行数据的还原

  • 物理备份 - 直接复制数据库的物理文件(如数据文件、日志文件),生成二进制备份文件。为了保证的数据的一致性与完整性,在执行物理备份之前,需要先将 MySQL 服务进行关闭,因此在有些资料中,这种物理备份形式也称冷备份。

    众所周知,每个表都拥有独立的 .ibd 文件,存储该表的所有数据和索引。InnoDB 默认使用独立表空间来创建表(innodb_file_per_table=1),若 innodb_file_per_table=0,则 InnoDB 默认使用系统表空间来创建表。

    show session variables like 'innodb_file_per_table';
    +-----------------------+-------+
    | Variable_name         | Value |
    +-----------------------+-------+
    | innodb_file_per_table | ON    |
    +-----------------------+-------+
    1 row in set (0.00 sec)
  • 物理恢复 - 通过替换数据库的物理文件来恢复数据库状态。

MySQL 自带的逻辑备份与逻辑恢复

逻辑备份的命令涉及到 mysqldump ,逻辑恢复涉及到 mysql 命令。

注意!在不添加任何选项的情况下,mysqldump 不会备份存储例程(存储过程以及存储函数),但会默认备份事件(Event)以及触发器(Trigger),若您有备份存储例程的需要,请添加 --routines 选项。在格式上,该命令备份出来的文件默认是文本格式,即使您使用相关的压缩选项,本质上也是文本格式。

版本提示
从 8.0.34 版本开始,mysqlpump 备份工具已被移除。

逻辑备份

在最初的演示中,作者曾导入过一个官方的 world 示例库,接下来,作者将演示备份该库的过程(在备份之前,请注意 MySQL 相关用户是否有备份权限,若忘记了 MySQL 用户管理的内容,请参阅 这里

select user,host from mysql.user;
+------------------+-----------+
| user             | host      |
+------------------+-----------+
| jimcat8          | %         |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

show grants for 'root'@'localhost';
# -B 选项指定要备份的库
Shell > /usr/local/mysql8/bin/mysqldump -h localhost -P 3306 -u root --password='MyNewPass4!' -B world > /tmp/world-2025-12-27.sql

# 头 10 行的内容
Shell > head -n 10 /tmp/world-2025-12-27.sql
-- MySQL dump 10.13  Distrib 8.4.6, for Linux (x86_64)
--
-- Host: localhost    Database: world
-- ------------------------------------------------------
-- Server version       8.4.6

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;

# 尾 10 行的内容
Shell > tail -n 10 /tmp/world-2025-12-27.sql

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2025-12-27 13:21:24

您也可以搭配 cron 计划任务工具来对数据库定时备份:

Shell > systemctl is-enabled crond.service
enabled

Shell > systemctl status crond.service
● crond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2025-12-27 13:08:28 CST; 40min ago
...

Shell > vim /root/DB_backup.sh
#!/bin/bash
date=$(date +%F)
# 为了保证完整性与一致性,开启全局锁
/usr/local/mysql8/bin/mysql -h localhost -P 3306 -u root --password='MyNewPass4!' -e "flush tables with read lock;" &&

# 全库备份
## -A 选项表示备份全部库
/usr/local/mysql8/bin/mysqldump -h localhost -P 3306 -u root --password='MyNewPass4!' -A --routines > /tmp/FullBackup-"$date".sql  && 

# 释放全局锁
/usr/local/mysql8/bin/mysql -h localhost -P 3306 -u root --password='MyNewPass4!' -e "unlock tables;"

Shell > chmod u+x /root/DB_backup.sh

# 每天的凌晨三点五分执行一次全量备份
Shell > crontab -e
5 3 * * * /root/DB_backup.sh &> /dev/null
提示
也可以使用 mysqldump 命令的 --single-transaction 选项来保证数据的完整性与一致性。

逻辑恢复

先将 world 库删除:

Shell > /usr/local/mysql8/bin/mysql -h localhost -u root --password="MyNewPass4!"
drop database world;

逻辑恢复的语法为:

mysql -h HostName -P 3306 -u root --passsword="String" < FileName.sql
Shell > /usr/local/mysql8/bin/mysql -h localhost -u root --password="MyNewPass4!" < /tmp/world-2025-12-27.sql

恢复成功:

show databases;
+--------------------+
| Database           |
+--------------------+
| home               |
| information_schema |
| locks              |
| mysql              |
| performance_schema |
| sys                |
| world              |
+--------------------+
7 rows in set (0.00 sec)

第三方物理备份工具 xtrabackup

xtrabackup 是由 percona 团队开源的、针对 MySQL 的一款免费热备份软件,其在备份期间不会锁定您的数据库,最新的版本为 8.4。

该工具的优点如下:

  1. 物理备份,快速、可靠
  2. 支持增量备份,更加地灵活
  3. 备份不会锁定数据库,也不会打断正在执行的事务
  4. 压缩功能,可节约磁盘空间与流量
  5. 备份校验,备份过程中校验备份文件的完整度
  6. 更快速的还原恢复
  7. 可使用基于流的备份,将备份传输到另外一个机器上

基本概念

  • 冷备份:也称离线备份,指关闭 DBMS 后进行的备份。备份的数据与系统中此时段的数据完全一致
  • 热备份:也称在线备份,指 DBMS 正在运行时进行的备份。由于系统中的数据随时在更新,备份的数据相对于系统的真实数据有一定的滞后
  • 异地备份:也称容灾,指将数据从一个位置备份到另外一个位置,这里 "另外一个位置" 可以指磁盘位置、服务器机器位置、地理位置、网络位置、数据中心位置等
  • 完整备份:指把硬盘或数据库内的所有文件、文件夹或数据作一次性的复制
  • 增量备份:指对上一次完整备份或增量备份后更新的数据进行备份。过程是这样的,比如第一天执行一次完整备份;第二天执行一次新增数据的备份(相对于前一天的全部备份而言);第三天在第二天的基础上再执行一次新增数据的备份(相对于前一天的增量备份而言),以此类推
  • 差异备份 :指完整备份后变更的文件的备份。如第一天执行完整备份;第二天备份新出现的数据(相对于完整备份而言);第三天备份第二天与第三天的新增数据;第四天备份第二天到第四天所有的新增数据,以此类推

安装 xtrabackup

在当前环境中安装 xtrabackup:

# 开启相关存储库并安装相关软件 
Shell > dnf install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
Shell > percona-release enable pxb-84-lts
Shell > dnf -y install percona-xtrabackup-84

# 验证安装
Shell > xtrabackup --version
2025-12-27T22:27:50.497163+08:00 0 [Note] [MY-011825] [Xtrabackup] recognized server arguments: --server-id=1 --datadir=/usr/local/mysql8/data/ --innodb_flush_log_at_trx_commit=1 --innodb_buffer_pool_size=1G --innodb_io_capacity=100
xtrabackup version 8.4.0-5 based on MySQL server 8.4.0 Linux (x86_64) (revision id: c6054e17)
提示
安装 xtrabackup 时要注意!xtrabackup 的版本需要与 MySQL Server 的版本对应,作者当前的 MySQL 为 8.4,则安装时的 xtrabackup 也应该是 8.4 版本。
    select version();
    +-----------+
    | version() |
    +-----------+
    | 8.4.6     |
    +-----------+
    1 row in set (0.01 sec)

xtrabackup 命令

备份的相关选项包括:

  • --defaults-file=/etc/my.cnf - 必须放在命令行的第一个选项上,指定 MySQL 的配置文件路径,必须是一个真实的文件,不能是软链接
  • --databases="db1[.tb1] db2[.tb2] …" - 选择库或者特定库的特定表,多个库用空格隔开。如果没有该选项,则选择的是所有库
  • --databases-file=FILE - 指定一个文件,文件中每一行写明你要备份的数据库或者表,每一行格式为——db1[.tb1]
  • --tables-file=FILE - 指定一个文件,文件中每一行写明要备份的表,每一行格式为——db1.tb1
  • --target-dir=DIR - 目标目录
  • --backup - 备份,需与 --target-dir=NAME 选项结合使用
  • --stream=NAME - 使用基于流的备份时所使用的格式,格式仅支持 xbstream
  • --throttle=# - 当磁盘负载较高时,用于限制每秒复制的区块数量(一个区块为10MB),仅适用于 --backup 期间。例如要将磁盘的 IO 限制在 50MB/s,则该值可以为 5
  • --incremental-basedir=DIR - 指定增量备份时完整备份/增量备份所在的目录
  • --incremental-lsn=NAME - 指定增量备份的 LSN (log sequence number,日志序列号)
  • --tmpdir=DIR - 指定备份期间用于存储临时文件的目录,可以指定多个,用英语的冒号分隔
  • --no-server-version-check - 当 MySQL DBMS 的版本大于 xtrabackup 支持的版本时,请选择该选项,需自行承担风险

连接 MySQL 的相关选项包括:

  • --user=USER - 连接 MySQL 服务器所使用的用户名
  • --password[=PASSWORD] - 连接到 MySQL 服务器时,对应用户所使用的密码,[ ] 表示可选
  • --host=HOST - 连接到 MySQL 服务器的主机
  • --port=# - 连接到 MySQL 服务器的端口,默认值3306
  • --datadir=DIR - MySQL 的数据目录

压缩的相关选项包括:

  • --compress=[name] - 指定压缩算法,压缩算法有lz4、zstd(默认压缩算法)
  • --compress-threads=N - 压缩时所使用的线程数,默认 1
  • --compress-chunk-size=N - 每个压缩线程所使用的工作缓冲区大小,单位为字节。默认值为 65536,即 64KB
  • --compress-zstd-level=# - ztsd 压缩算法所使用的压缩级别,值范围为 1~19,默认 1。值越大,压缩程度越高,文件体积越小
  • --decompress - 解压文件

加密或解密的相关选项包括:

  • --encrypt=NAME - 使用哪个加密算法对备份文件进行加密,支持的算法有:AES128、AES192、AES256
  • --encrypt-threads=# - 对备份文件进行加密/解密操作时所使用的工作线程数,默认值为 1
  • --encrypt-chunk-size=# - 每个加密线程所使用的内部工作缓冲区大小,单位为字节,默认值为65536,即 64KB

还原的相关选项包括:

  • --prepare - 对 --backup 创建的备份进行还原的准备
  • --rebuild-indexes - 还原时重建索引,只能与 --prepare 和 --rebuild-threads 一起使用
  • --rebuild-threads=# - 重建索引所使用的线程数,默认值为 1,只能与 --prepare 和 --rebuild-indexes 一起使用
  • --use-memory=# - 准备还原时要使用多少内存,常与 --apply-log-only 一起使用,单位为字节,默认值为 104857600,即 100MB。当然也可以直接写类似如 200MB、1G 这样的值。推荐的值为 1G~2G
  • --apply-log-only - 还原时的重要选项,确保多个备份集能按顺序合并,而不会过早完成恢复过程。如单词的含义一样,表示仅应用事务日志但不最终提交
  • --incremental-dir=DIR - 增量备份目录
  • --copy-back - 将完全准备好的文件复制到 MySQL 服务器的数据目录中
提示
完整备份文件以及增量备份文件不能存放在一个目录中,每个增量备份文件都需要专有的目录进行存放,否则会出现 "OS errno 17 - File exists" 错误提示。

完整备份示例

Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password="MyNewPass4!" --host=localhost --backup --target-dir=/root/fullbackup
...
2025-12-27T22:34:05.950071+08:00 0 [Note] [MY-011825] [Xtrabackup] Copying ib_buffer_pool to /root/fullbackup/ib_buffer_pool
2025-12-27T22:34:05.950199+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Copying ib_buffer_pool to /root/fullbackup/ib_buffer_pool
2025-12-27T22:34:05.950994+08:00 0 [Note] [MY-011825] [Xtrabackup] Backup created in directory '/root/fullbackup/'
2025-12-27T22:34:05.951051+08:00 0 [Note] [MY-011825] [Xtrabackup] MySQL binlog position: filename 'binlog.000068', position '158'
2025-12-27T22:34:05.951231+08:00 0 [Note] [MY-011825] [Xtrabackup] Writing /root/fullbackup/backup-my.cnf
2025-12-27T22:34:05.951737+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Writing file /root/fullbackup/backup-my.cnf
2025-12-27T22:34:05.952778+08:00 0 [Note] [MY-011825] [Xtrabackup] Writing /root/fullbackup/xtrabackup_info
2025-12-27T22:34:05.953150+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Writing file /root/fullbackup/xtrabackup_info
2025-12-27T22:34:06.955138+08:00 0 [Note] [MY-011825] [Xtrabackup] Transaction log of lsn (26573406) to (26573406) was copied.
2025-12-27T22:34:07.159636+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

# 目录结构以及目录下的文件如下
Shell > tree /root/fullbackup/
/root/fullbackup/
├── backup-my.cnf
├── binlog.000068
├── binlog.index
├── home
│   ├── homewallet.ibd
│   └── wallettype.ibd
├── ib_buffer_pool
├── ibdata1
├── locks
│   ├── t1.ibd
│   ├── tb1.ibd
│   ├── tindex1.ibd
│   └── tlock1.ibd
├── mysql
│   ├── general_log_214.sdi
│   ├── general_log.CSM
│   ├── general_log.CSV
│   ├── slow_log_215.sdi
│   ├── slow_log.CSM
│   └── slow_log.CSV
├── mysql.ibd
├── performance_schema
│   ├── accounts_146.sdi
│   ├── binary_log_trans_190.sdi
│   ├── cond_instances_81.sdi
│   ├── data_locks_161.sdi
│   ├── data_lock_waits_162.sdi
│   ├── error_log_82.sdi
│   ├── events_errors_su_140.sdi
│   ├── events_errors_su_141.sdi
│   ├── events_errors_su_142.sdi
│   ├── events_errors_su_143.sdi
│   ├── events_errors_su_144.sdi
│   ├── events_stages_cu_112.sdi
│   ├── events_stages_hi_113.sdi
│   ├── events_stages_hi_114.sdi
│   ├── events_stages_su_115.sdi
│   ├── events_stages_su_116.sdi
│   ├── events_stages_su_117.sdi
│   ├── events_stages_su_118.sdi
│   ├── events_stages_su_119.sdi
│   ├── events_statement_120.sdi
│   ├── events_statement_121.sdi
│   ├── events_statement_122.sdi
│   ├── events_statement_123.sdi
│   ├── events_statement_124.sdi
│   ├── events_statement_125.sdi
│   ├── events_statement_126.sdi
│   ├── events_statement_127.sdi
│   ├── events_statement_128.sdi
│   ├── events_statement_129.sdi
│   ├── events_statement_130.sdi
│   ├── events_statement_131.sdi
│   ├── events_transacti_132.sdi
│   ├── events_transacti_133.sdi
│   ├── events_transacti_134.sdi
│   ├── events_transacti_135.sdi
│   ├── events_transacti_136.sdi
│   ├── events_transacti_137.sdi
│   ├── events_transacti_138.sdi
│   ├── events_transacti_139.sdi
│   ├── events_waits_cur_83.sdi
│   ├── events_waits_his_84.sdi
│   ├── events_waits_his_85.sdi
│   ├── events_waits_sum_86.sdi
│   ├── events_waits_sum_87.sdi
│   ├── events_waits_sum_88.sdi
│   ├── events_waits_sum_89.sdi
│   ├── events_waits_sum_90.sdi
│   ├── events_waits_sum_91.sdi
│   ├── file_instances_92.sdi
│   ├── file_summary_by__93.sdi
│   ├── file_summary_by__94.sdi
│   ├── global_status_182.sdi
│   ├── global_variables_185.sdi
│   ├── host_cache_95.sdi
│   ├── hosts_147.sdi
│   ├── keyring_componen_192.sdi
│   ├── keyring_keys_153.sdi
│   ├── log_status_175.sdi
│   ├── memory_summary_b_155.sdi
│   ├── memory_summary_b_156.sdi
│   ├── memory_summary_b_157.sdi
│   ├── memory_summary_b_158.sdi
│   ├── memory_summary_g_154.sdi
│   ├── metadata_locks_160.sdi
│   ├── mutex_instances_96.sdi
│   ├── objects_summary__97.sdi
│   ├── performance_time_98.sdi
│   ├── persisted_variab_188.sdi
│   ├── prepared_stateme_176.sdi
│   ├── processlist_99.sdi
│   ├── replication_appl_166.sdi
│   ├── replication_appl_167.sdi
│   ├── replication_appl_168.sdi
│   ├── replication_appl_169.sdi
│   ├── replication_appl_171.sdi
│   ├── replication_appl_172.sdi
│   ├── replication_asyn_173.sdi
│   ├── replication_asyn_174.sdi
│   ├── replication_conn_163.sdi
│   ├── replication_conn_165.sdi
│   ├── replication_grou_164.sdi
│   ├── replication_grou_170.sdi
│   ├── rwlock_instances_100.sdi
│   ├── session_account__152.sdi
│   ├── session_connect__151.sdi
│   ├── session_status_183.sdi
│   ├── session_variable_186.sdi
│   ├── setup_actors_101.sdi
│   ├── setup_consumers_102.sdi
│   ├── setup_instrument_103.sdi
│   ├── setup_meters_104.sdi
│   ├── setup_metrics_105.sdi
│   ├── setup_objects_106.sdi
│   ├── setup_threads_107.sdi
│   ├── socket_instances_148.sdi
│   ├── socket_summary_b_149.sdi
│   ├── socket_summary_b_150.sdi
│   ├── status_by_accoun_178.sdi
│   ├── status_by_host_179.sdi
│   ├── status_by_thread_180.sdi
│   ├── status_by_user_181.sdi
│   ├── table_handles_159.sdi
│   ├── table_io_waits_s_108.sdi
│   ├── table_io_waits_s_109.sdi
│   ├── table_lock_waits_110.sdi
│   ├── threads_111.sdi
│   ├── tls_channel_stat_191.sdi
│   ├── user_defined_fun_189.sdi
│   ├── users_145.sdi
│   ├── user_variables_b_177.sdi
│   ├── variables_by_thr_184.sdi
│   └── variables_info_187.sdi
├── sys
│   └── sys_config.ibd
├── undo_001
├── undo_002
├── world
│   ├── city.ibd
│   ├── country.ibd
│   └── countrylanguage.ibd
├── xtrabackup_binlog_info
├── xtrabackup_checkpoints
├── xtrabackup_info
├── xtrabackup_logfile
└── xtrabackup_tablespaces

6 directories, 141 files

Shell > du -sh /root/fullbackup/
74M     /root/fullbackup/

从备份出的文件可知,大致有两大类文件:

  • MySQL 本身相关的文件
  • 与 xtrabackup 相关的文件

若使用压缩,比较下两者文件的大小:

Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password="MyNewPass4!" --host=localhost --backup --target-dir=/root/comp-fullbackup --compress=zstd --compress-zstd-level=10

# 这个文件大小的占用堪比黑科技
Shell > du -sh /root/comp-fullbackup/
2.1M    /root/comp-fullbackup/

第一次增量备份

基于 /root/comp-fullbackup/ 目录,在完整备份的基础上新增增量备份,当然,MySQL 需要新增数据:

use locks;

create table if not exists incre_tmp(
    id int primary key auto_increment,
    description text not null
);

insert into incre_tmp values(null, '这是一段简单的文本内容');
# 因为完整备份使用的是 zstd 压缩算法,因此此处的增量备份也应该使用 zstd 算法
Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password="MyNewPass4!" --host=localhost --backup --target-dir=/root/inc1/ --incremental-basedir=/root/comp-fullbackup/ --compress=zstd
...
2025-12-27T22:56:07.506032+08:00 0 [Note] [MY-011825] [Xtrabackup] Executing UNLOCK INSTANCE
2025-12-27T22:56:07.506205+08:00 0 [Note] [MY-011825] [Xtrabackup] All tables unlocked
2025-12-27T22:56:07.506237+08:00 0 [Note] [MY-011825] [Xtrabackup] Total time Server is locked by LOCK INSTANCE FOR BACKUP is: 2.618 seconds
2025-12-27T22:56:07.506305+08:00 0 [Note] [MY-011825] [Xtrabackup] Compressing ib_buffer_pool to /root/inc1/ib_buffer_pool.zst
2025-12-27T22:56:07.506692+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Compressing ib_buffer_pool to /root/inc1/ib_buffer_pool.zst
2025-12-27T22:56:07.507413+08:00 0 [Note] [MY-011825] [Xtrabackup] Backup created in directory '/root/inc1/'
2025-12-27T22:56:07.507447+08:00 0 [Note] [MY-011825] [Xtrabackup] MySQL binlog position: filename 'binlog.000070', position '158'
2025-12-27T22:56:07.507545+08:00 0 [Note] [MY-011825] [Xtrabackup] Compressing /root/inc1/backup-my.cnf.zst
2025-12-27T22:56:07.507593+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Compressing file /root/inc1/backup-my.cnf.zst
2025-12-27T22:56:07.508519+08:00 0 [Note] [MY-011825] [Xtrabackup] Compressing /root/inc1/xtrabackup_info.zst
2025-12-27T22:56:07.508570+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Compressing file /root/inc1/xtrabackup_info.zst
2025-12-27T22:56:08.510959+08:00 0 [Note] [MY-011825] [Xtrabackup] Transaction log of lsn (26587829) to (26587829) was copied.
2025-12-27T22:56:08.725135+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

第二次增量备份

基于 /root/inc1/ 目录,在原有增量备份基础上再次新增增量备份,当然,MySQL 需要新增数据:

use locks;

create table if not exists incre2_tmp(
    id int primary key auto_increment,
    description text not null
);

insert into incre2_tmp values(null, '增量备份的文本内容');
Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password="MyNewPass4!" --host=localhost --backup --target-dir=/root/inc2/ --incremental-basedir=/root/inc1/ --compress=zstd
...
2025-12-27T23:01:17.908983+08:00 0 [Note] [MY-011825] [Xtrabackup] Compressing /root/inc2/xtrabackup_info.zst
2025-12-27T23:01:17.909037+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Compressing file /root/inc2/xtrabackup_info.zst
2025-12-27T23:01:18.910670+08:00 0 [Note] [MY-011825] [Xtrabackup] Transaction log of lsn (26604294) to (26604294) was copied.
2025-12-27T23:01:19.123214+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

最后,检查完整备份以及增量备份的 LSN 信息:

Shell > cat /root/comp-fullbackup/xtrabackup_checkpoints
backup_type = full-backuped
from_lsn = 0
to_lsn = 26573416
last_lsn = 26573416
flushed_lsn = 26573416
redo_memory = 0
redo_frames = 0

Shell > cat /root/inc1/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 26573416
to_lsn = 26587829
last_lsn = 26587829
flushed_lsn = 26587829
redo_memory = 0
redo_frames = 0

Shell > cat /root/inc2/xtrabackup_checkpoints
backup_type = incremental
from_lsn = 26587829
to_lsn = 26604294
last_lsn = 26604294
flushed_lsn = 26604294
redo_memory = 0
redo_frames = 0

上面备份的逻辑是 —— 完整备份(时间点1)>>> 增量备份(时间点2)>>> 增量备份(时间点3)

还原

为了方便演示,将 locks 先进行删除:

drop database locks;

还原时,把各个时间点的备份按照先后顺序进行恢复,比如需要恢复到时间点3的数据,需要先把在它之前时间点的数据恢复,具体的操作如下:

# 由于上述的备份都是压缩文件,因此首先需要进行解压缩
Shell > xtrabackup --decompress --target-dir=/root/comp-fullbackup/
Shell > xtrabackup --decompress --target-dir=/root/inc1/
Shell > xtrabackup --decompress --target-dir=/root/inc2/

# 恢复到时间点1
## \ 表示内容还没有结束
Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password='MyNewPass4!' --host=localhost \
--prepare --apply-log-only  --target-dir=/root/comp-fullbackup/
...
2025-12-27T23:25:37.099024+08:00 0 [Note] [MY-013084] [InnoDB] Log background threads are being closed...
2025-12-27T23:25:37.141209+08:00 0 [Note] [MY-012980] [InnoDB] Shutdown completed; log sequence number 26573426
2025-12-27T23:25:37.147718+08:00 0 [Note] [MY-015019] [Server] MySQL Server: Plugins Shutdown - start.
2025-12-27T23:25:37.147795+08:00 0 [Note] [MY-015020] [Server] MySQL Server: Plugins Shutdown - end.
2025-12-27T23:25:37.148657+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

# 恢复到时间点2
## \ 表示内容还没有结束
Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password='MyNewPass4!' --host=localhost \
--prepare --apply-log-only  --target-dir=/root/comp-fullbackup/ --incremental-dir=/root/inc1/
...
2025-12-27T23:28:24.166078+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Copying /root/inc1/binlog.index to ./binlog.index
2025-12-27T23:28:24.166454+08:00 0 [Note] [MY-015019] [Server] MySQL Server: Plugins Shutdown - start.
2025-12-27T23:28:24.166479+08:00 0 [Note] [MY-015020] [Server] MySQL Server: Plugins Shutdown - end.
2025-12-27T23:28:24.166793+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

# 恢复到时间点3
## \ 表示内容还没有结束
## 由于这是最后一个准备阶段,因此不再需要 --apply-log-only 
Shell > xtrabackup --defaults-file=/etc/my.cnf --user=root --password='MyNewPass4!' --host=localhost \
--prepare  --target-dir=/root/comp-fullbackup/ --incremental-dir=/root/inc2/
...
2025-12-27T23:30:33.567569+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Copying /root/inc2/binlog.index to ./binlog.index
2025-12-27T23:30:33.568000+08:00 0 [Note] [MY-015019] [Server] MySQL Server: Plugins Shutdown - start.
2025-12-27T23:30:33.568034+08:00 0 [Note] [MY-015020] [Server] MySQL Server: Plugins Shutdown - end.
2025-12-27T23:30:33.568348+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

文件内容发生了变化:

Shell > cat /root/comp-fullbackup/xtrabackup_checkpoints
backup_type = full-prepared  ←← 这里
from_lsn = 0
to_lsn = 26604294
last_lsn = 26604294
flushed_lsn = 26604294
redo_memory = 0
redo_frames = 0

关闭当前正在运行的 MySQL 实例:

Shell > /usr/local/mysql8/bin/mysqladmin -h localhost -u root --password="MyNewPass4!" shutdown

模拟数据丢失(将 MySQL 的数据目录删除):

Shell > rm -rf /usr/local/mysql8/data/

开始进行数据的还原:

Shell > xtrabackup --copy-back --target-dir=/root/comp-fullbackup/
...
2025-12-27T23:36:09.238476+08:00 1 [Note] [MY-011825] [Xtrabackup] Copying ./performance_schema/events_waits_sum_87.sdi to /usr/local/mysql8/data/performance_schema/events_waits_sum_87.sdi
2025-12-27T23:36:09.238712+08:00 1 [Note] [MY-011825] [Xtrabackup] Done: Copying ./performance_schema/events_waits_sum_87.sdi to /usr/local/mysql8/data/performance_schema/events_waits_sum_87.sdi
2025-12-27T23:36:09.278646+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

Shell > ls -lh /usr/local/mysql8/data/
total 83M
-rw-r----- 1 root root  158 Dec 27 23:36  binlog.000071
-rw-r----- 1 root root   14 Dec 27 23:36  binlog.index
drwxr-x--- 2 root root 4.0K Dec 27 23:36  home
-rw-r----- 1 root root 4.0K Dec 27 23:36  ib_buffer_pool
-rw-r----- 1 root root  12M Dec 27 23:36  ibdata1
-rw-r----- 1 root root  12M Dec 27 23:36  ibtmp1
drwxr-x--- 2 root root 4.0K Dec 27 23:36 '#innodb_redo'
drwxr-x--- 2 root root 4.0K Dec 27 23:36  locks
drwxr-x--- 2 root root 4.0K Dec 27 23:36  mysql
-rw-r----- 1 root root  26M Dec 27 23:36  mysql.ibd
drwxr-x--- 2 root root 4.0K Dec 27 23:36  performance_schema
drwxr-x--- 2 root root 4.0K Dec 27 23:36  sys
-rw-r----- 1 root root  16M Dec 27 23:36  undo_001
-rw-r----- 1 root root  16M Dec 27 23:36  undo_002
drwxr-x--- 2 root root 4.0K Dec 27 23:36  world
-rw-r----- 1 root root  638 Dec 27 23:36  xtrabackup_info  ←← 这是一个新增的文件

# 递归变更文件的所有者以及相关权限
Shell > chown -R mysql:mysql /usr/local/mysql8/data/ && chmod -R 755 /usr/local/mysql8/data/

# 启动服务器实例
Shell > /usr/local/mysql8/bin/mysqld_safe --user=mysql &

# 数据已经恢复
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| home               |
| information_schema |
| locks              |
| mysql              |
| performance_schema |
| sys                |
| world              |
+--------------------+
7 rows in set (0.00 sec)

mysql> show tables from locks;
+-----------------+
| Tables_in_locks |
+-----------------+
| incre2_tmp      |
| incre_tmp       |
| t1              |
| tb1             |
| tindex1         |
| tlock1          |
+-----------------+
6 rows in set (0.00 sec)

xtrabackup 拓展内容

除了常规的完整备份、增量备份外,使用者还可以使用基于流的备份。您可以在单台机器上使用流备份,也可以在两台机器上使用流备份。

两台机器

首先需要开启非对称加密算法来进行身份验证:

Shell (Source) > ssh-keygen -t rsa -b 2048

# 将公钥传输给目标机器
Shell (Source) > ssh-copy-id -p 22 root@192.168.100.21 

# 目标机器开启公钥验证
## 目标机器既可以使用用户密码进行验证登录,也可以使用公钥私钥进行验证登录
Shell (Target) > vim /etc/ssh/sshd.conf
…
PubkeyAuthentication yes  
…

Shell (Target) > systemctl restart sshd.service
# 生产环境下建议开启压缩功能
## \ 表示命令还没有结束
Shell (Source) > xtrabackup --defaults-file=/etc/my.cnf --user=root --password='MyNewPass4!' --host=localhost --backup \
--stream=xbstream --compress=zstd --target-dir=/tmp/stream/ > /root/fullbackup-$(date +%F).stream.zst
...
2025-12-28T15:25:10.479986+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Compressing and streaming file <STDOUT>
2025-12-28T15:25:10.480482+08:00 0 [Note] [MY-011825] [Xtrabackup] Compressing and streaming <STDOUT>
2025-12-28T15:25:10.480519+08:00 0 [Note] [MY-011825] [Xtrabackup] Done: Compressing and streaming file <STDOUT>
2025-12-28T15:25:11.481017+08:00 0 [Note] [MY-011825] [Xtrabackup] Transaction log of lsn (26699681) to (26699681) was copied.
2025-12-28T15:25:11.700724+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

Shell (Source) > ls -lh /root/fullbackup-2025-12-28.stream.zst
-rw-r--r-- 1 root root 1.9M Dec 28 15:25 /root/fullbackup-2025-12-28.stream.zst

# 利用 scp 命令将文件传输给目标机器
Shell (Source) > scp -P 22 /root/fullbackup-$(date +%F).stream.zst root@192.168.100.21:/tmp/

假设 Source 机器的 MySQL 实例需要恢复数据:

# 将 Target 机器上的压缩流文件传输到 Source 机器上
Shell (Source) > scp -P 22 root@192.168.100.21:/tmp/fullbackup-2025-12-28.stream.zst /root/

# 创建存放目录
Shell (Source) > mkdir /root/stream-dir/

# 利用 xbstream 命令先提取出文件
Shell (Source) > xbstream -x < /root/fullbackup-2025-12-28.stream.zst -C /root/stream-dir/

# 解压这些 zst 文件
Shell (Source) > xtrabackup --decompress --target-dir=/root/stream-dir/
...
2025-12-28T16:07:14.050259+08:00 0 [Note] [MY-011825] [Xtrabackup] decompressing ./performance_schema/user_defined_fun_189.sdi.zst
2025-12-28T16:07:14.053240+08:00 0 [Note] [MY-011825] [Xtrabackup] decompressing ./performance_schema/setup_objects_106.sdi.zst
2025-12-28T16:07:14.056855+08:00 0 [Note] [MY-011825] [Xtrabackup] decompressing ./performance_schema/events_stages_su_118.sdi.zst
2025-12-28T16:07:14.059889+08:00 0 [Note] [MY-011825] [Xtrabackup] decompressing ./backup-my.cnf.zst
2025-12-28T16:07:14.121312+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

# 恢复准备(这里不需要 --apply-log-only 选项)
## 若您备份时采用的是 "完整备份 + 多个增量备份",则在最后一个准备阶段(最后一个增量备份)时不需要添加 --apply-log-only 选项
Shell (Source) > xtrabackup --prepare --target-dir=/root/stream-dir/
...
2025-12-28T17:25:49.299909+08:00 0 [Note] [MY-013072] [InnoDB] Starting shutdown...
2025-12-28T17:25:49.404422+08:00 0 [Note] [MY-013084] [InnoDB] Log background threads are being closed...
2025-12-28T17:25:49.439127+08:00 0 [Note] [MY-012980] [InnoDB] Shutdown completed; log sequence number 26699798
2025-12-28T17:25:49.443827+08:00 0 [Note] [MY-015019] [Server] MySQL Server: Plugins Shutdown - start.
2025-12-28T17:25:49.443874+08:00 0 [Note] [MY-015020] [Server] MySQL Server: Plugins Shutdown - end.
2025-12-28T17:25:49.444417+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

# 关闭 MySQL 服务器实例
Shell (Source) > /usr/local/mysql8/bin/mysqladmin -u root --password="MyNewPass4!" shutdown

# 模拟数据丢失(将 MySQL 的数据目录删除)
Shell (Source) > rm -rf /usr/local/mysql8/data/

# 开始数据还原
Shell (Source) > xtrabackup --copy-back --target-dir=/root/stream-dir/
...
2025-12-28T17:30:38.251743+08:00 1 [Note] [MY-011825] [Xtrabackup] Copying ./performance_schema/events_waits_sum_87.sdi to /usr/local/mysql8/data/performance_schema/events_waits_sum_87.sdi
2025-12-28T17:30:38.252020+08:00 1 [Note] [MY-011825] [Xtrabackup] Done: Copying ./performance_schema/events_waits_sum_87.sdi to /usr/local/mysql8/data/performance_schema/events_waits_sum_87.sdi
2025-12-28T17:30:38.323393+08:00 0 [Note] [MY-011825] [Xtrabackup] completed OK!

# 递归变更数据目录的所有者所属组以及对应权限
Shell (Source) > chown -R mysql:mysql /usr/local/mysql8/data/ && chmod -R 755 /usr/local/mysql8/data/

# 启动 MySQL 服务器实例,恢复完成
Shell (Source) > /usr/local/mysql8/bin/mysqld_safe --user=mysql &

若您觉得上述基于流的完整备份步骤过于麻烦,也可以使用脚本搭配 cron ,如下:

Shell (Source) > vim /root/my-fullbackup-stream.sh
#!/bin/bash
date=$(date +%F)

xtrabackup --defaults-file=/etc/my.cnf --user=root --password='MyNewPass4!' --host=localhost --backup \
--stream=xbstream --compress=zstd --target-dir=/tmp/stream/ > /root/fullbackup-"$date".stream.zst

cd /root/ && scp -P 22 /root/fullbackup-"$date".stream.zst root@192.168.100.21:/tmp/

Shell (Source) > chmod u+x /root/my-fullbackup-stream.sh

# 每天的凌晨三点执行一次完全备份
Shell > crontab -e 
0 3 * * * /root/my-fullbackup-stream.sh &> /dev/null
提示
基于流的备份除了单一的完整备份外,也可以是 "完整备份 + 多个增量备份"
Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇