1.创建备份专用用户

Percona XtraBackup需要能够连接到数据库服务器,并在创建备份时、在某些场景下准备备份以及在还原备份时执行操作。为了实现这一点,对其执行所需的Privilege和权限Permissions要求必须得到满足。

  • Privilege:指的是系统用户在数据库服务器中被允许执行的操作。它们在数据库服务器上设置,仅适用于数据库服务器中的用户。
  • Permissions: 允许用户在系统上执行操作,比如在某个目录上读取、写入或执行,或者启动/停止系统服务。它们在系统级别上设置,仅适用于系统用户。

当使用xtrabackup时,涉及到两个用户:

  • 一个系统用户 - 调用程序的用户
  • 一个数据库用户 - 以及在数据库服务器中执行操作的用户

需要注意,这些是不同的用户,虽然它们可能具有相同的用户名,但是在不同的位置上。

对于数据库用户虽然可以使用root用户,但还是建议创建一个专门用于备份的数据库用户,此用户需要以下权限(Privilege)才能备份表或数据库:

  1. RELOADLOCK TABLES(除非指定了--no-lock选项)以便在开始复制文件之前运行FLUSH TABLES WITH READ LOCKFLUSH ENGINE LOGS,当使用Backup Locks 时,需要此权限。
  2. 需要BACKUP_ADMIN来查询performance_schema.log_status表,并运行LOCK INSTANCE FOR BACKUPLOCK BINLOG FOR BACKUPLOCK TABLES FOR BACKUP
  3. 需要REPLICATION CLIENT权限以获取二进制日志位置信息。
  4. 需要CREATE TABLESPACE权限以导入表(还原单独的表时有用)。
  5. 需要PROCESS权限以运行SHOW ENGINE INNODB STATUS(这是必需的),并且选择性地查看在服务器上运行的所有线程。
  6. 需要SUPER权限以在复制环境中启动/停止复制线程,使用XtraDB Changed Page Tracking进行增量备份,并处理·FLUSH TABLES WITH READ LOCK·。
  7. 需要CREATE权限以创建PERCONA_SCHEMA.xtrabackup_history数据库和表。
  8. 需要ALTER权限以升级PERCONA_SCHEMA.xtrabackup_history数据库和表。
  9. 需要INSERT权限以将历史记录添加到PERCONA_SCHEMA.xtrabackup_history表。
  10. 需要SELECT权限以在使用--incremental-history-name--incremental-history-uuid时,允许特性在PERCONA_SCHEMA.xtrabackup_history表中查找innodb_to_lsn值。
  11. 在使用keyring时,需要在keyring_component_status表上具有SELECT权限,以查看已安keyring组件的属性和状态。
  12. 需要在replication_group_members表上具有 SELECT 权限,以验证实例是否属于组复制集群。

创建一个具备进行完整备份所需最小特权的数据库用户的 SQL 示例如下:

1CREATE USER 'bkpuser'@'localhost' IDENTIFIED BY 's3cr%T';
2GRANT BACKUP_ADMIN, PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT,CREATE TABLESPACE ON *.* TO 'bkpuser'@'localhost';
3GRANT SELECT ON performance_schema.log_status TO 'bkpuser'@'localhost';
4GRANT SELECT ON performance_schema.keyring_component_status TO bkpuser@'localhost';
5GRANT SELECT ON performance_schema.replication_group_members TO bkpuser@'localhost';
6FLUSH PRIVILEGES;

请确保将s3cr%T替换为要为bkpuser设置的实际密码,并根据需要调整主机地址。以上SQL语句将创建一个名为bkpuser的数据库用户,并授予所需的最小权限,以便执行备份操作。

创建完成后可以使用下面的命令查询此用户的权限:

 1mysql> SHOW GRANTS FOR 'bkpuser'@'localhost';
 2
 3+------------------------------------------------------------------------------------------------------------------+
 4| Grants for bkpuser@localhost                                                                              |
 5+------------------------------------------------------------------------------------------------------------------+
 6| GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT, CREATE TABLESPACE ON *.* TO `bkpuser`@`localhost` |
 7| GRANT BACKUP_ADMIN ON *.* TO `bkpuser`@`localhost`                                                        |
 8| GRANT SELECT, INSERT, CREATE, ALTER ON `PERCONA_SCHEMA`.`xtrabackup_history` TO `bkpuser`@`localhost`     |
 9| GRANT SELECT ON `performance_schema`.`keyring_component_status` TO `bkpuser`@`localhost`                  |
10| GRANT SELECT ON `performance_schema`.`log_status` TO `bkpuser`@`localhost`                                |
11| GRANT SELECT ON `performance_schema`.`replication_group_members` TO `bkpuser`@`localhost`                 |
12+------------------------------------------------------------------------------------------------------------------+
136 rows in set (0.00 sec)

2.全量备份

2.1 创建全量备份

要启动备份过程,请运行以下命令:

1xtrabackup --defaults-file=/etc/my.cnf --backup \
2        --user=bkpuser --password --host=localhost --port=3306 \
3        --use-memory=1GB --rsync \
4        --target-dir=/home/mysql/backups/2023-08-22
  • --backup表示以backup模式运行xtrabackup,在目标目录中创建备份
  • --defaults-file 表示仅从给定文件中读取默认选项,配置为要备份的MySQL实例的配置文件
  • --user 此选项指定连接到服务器时使用的 MySQL 用户名
  • --password没有直接给定密码,这将提示用户手动输入密码
  • --target-dir选项,该选项指定备份将存储的位置。如果InnoDB数据或日志文件不存储在同一目录中,可能还需要指定它们的位置。如果目标目录不存在,xtrabackup将创建它。如果目录已经存在且为空,xtrabackup将成功执行。xtrabackup不会覆盖现有文件,如果存在文件,它将失败并显示文件已经存在的错误。

启动备份后,将在/home/mysql/backups/2023-08-22中存储备份。

在备份过程中,会看到大量输出,显示数据文件正在被复制,以及日志文件线程重复扫描日志文件并从中复制数据。以下是一个示例,显示了后台中的日志线程扫描日志,以及一个正在处理ibdata1文件的文件复制线程:

 1160906 10:19:17 Finished backing up non-InnoDB tables and files
 2160906 10:19:17 Executing FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS...
 3xtrabackup: The latest check point (for incremental): '62988944'
 4xtrabackup: Stopping log copying thread.
 5.160906 10:19:18 >> log scanned up to (137343534)
 6160906 10:19:18 Executing UNLOCK TABLES
 7160906 10:19:18 All tables unlocked
 8160906 10:19:18 Backup created in directory '/home/mysql/backups/2023-08-22/'
 9160906 10:19:18 [00] Writing backup-my.cnf
10160906 10:19:18 [00]        ...done
11160906 10:19:18 [00] Writing xtrabackup_info
12160906 10:19:18 [00]        ...done
13xtrabackup: Transaction log of lsn (26970807) to (137343534) was copied.
14160906 10:19:18 completed OK!

你最后应该会看到类似以下内容的输出,其中<LSN>的值将是一个依赖于你的系统的数字:

1xtrabackup: Transaction log of lsn (<LSN>) to (<LSN>) was copied.

注意:日志复制线程每秒钟检查事务日志,以查看是否有新的日志记录需要复制,但有可能日志复制线程无法跟上写入事务日志的数量,从而在日志记录被覆盖之前无法读取时遇到错误。

备份完成后,目标目录将包含诸如以下文件(假设你有一个名为test.tbl1的单个InnoDB表,并且正在使用MySQL的innodb_file_per_table选项):

1$ ls -lh /data/backups/

结果应该类似于这样:

 1total 182M
 2drwx------  7 root root 4.0K Sep  6 10:19 .
 3drwxrwxrwt 11 root root 4.0K Sep  6 11:05 ..
 4-rw-r-----  1 root root  387 Sep  6 10:19 backup-my.cnf
 5-rw-r-----  1 root root  76M Sep  6 10:19 ibdata1
 6drwx------  2 root root 4.0K Sep  6 10:19 mysql
 7drwx------  2 root root 4.0K Sep  6 10:19 performance_schema
 8drwx------  2 root root 4.0K Sep  6 10:19 sbtest
 9drwx------  2 root root 4.0K Sep  6 10:19 test
10drwx------  2 root root 4.0K Sep  6 10:19 world2
11-rw-r-----  1 root root  116 Sep  6 10:19 xtrabackup_checkpoints
12-rw-r-----  1 root root  433 Sep  6 10:19 xtrabackup_info
13-rw-r-----  1 root root 106M Sep  6 10:19 xtrabackup_logfile

备份可能需要很长时间,具体取决于数据库的大小。你可以随时安全地取消备份,因为xtrabackup不会修改数据库。

接下来的步骤是准备备份以便恢复数据。

2.2 准备(Prepare)全量备份

在使用--backup选项创建完备份之后,需要对其进行准备,以便进行恢复。数据文件在进行准备之前不是处于时间点一致状态,因为它们在程序运行时在不同的时间点被复制,并且在此期间可能已被更改。

如果尝试使用这些数据文件启动InnoDB,它会检测到损坏并停止工作,以避免在损坏的数据上运行。--prepare步骤将文件在一个单一的时间点上使其完全一致,这样就可以在其上运行InnoDB。

可以在任何机器上运行准备操作;它不需要在原始服务器上或打算恢复到的服务器上运行。可以将备份复制到一个实用程序服务器并在那里进行准备。

请注意,Percona XtraBackup 8.0 只能准备 MySQL 8.0、Percona Server for MySQL 8.0 和 Percona XtraDB Cluster 8.0 数据库的备份。8.0 之前的版本不受支持。

在准备操作期间,xtrabackup 启动了一种修改过的嵌入式 InnoDB(链接到 xtrabackup 的库)。这些修改是必要的,以禁用InnoDB的标准安全检查,例如对日志文件大小不正确的警报。这个警告不适用于备份操作。这些修改仅适用于xtrabackup二进制文件;无需修改InnoDB即可使用xtrabackup进行备份。

准备步骤使用这个“嵌入式 InnoDB”在复制的数据文件上执行崩溃恢复,使用复制的日志文件。准备步骤非常简单:只需使用-prepare选项运行 xtrabackup,并告诉它要准备的目录,例如,要准备先前创建的备份,运行以下命令:

1xtrabackup --prepare --target-dir=/home/mysql/backups/2023-08-22

当此操作完成时,你应该会看到一个 InnoDB 关闭的消息,消息类似下面的内容,其中 LSN 的值将取决于你的系统:

1InnoDB: Shutdown completed; log sequence number 137345046
2160906 11:21:01 completed OK!

所有后续的准备操作都不会更改已准备好的数据文件,你会看到输出显示:

1xtrabackup: This target seems to be already prepared.
2xtrabackup: notice: xtrabackup_logfile was already used to '--prepare'.

不建议在准备备份过程中中断xtrabackup进程,因为这可能会导致数据文件损坏,备份将变得不可用。如果准备过程被中断,备份的有效性将无法保证。

如果你打算将备份用作进一步的增量备份的基础,你应该在准备备份时使用--apply-log-only选项,否则你将无法对其应用增量备份。

在准备完备份后,就可以恢复备份数据。

2.3 还原全量备份

注意: 备份在恢复之前需要进行准备。

为了方便起见,xtrabackup提供了--copy-back选项,可以将备份复制到服务器的数据目录中:

1xtrabackup --copy-back --target-dir=/home/mysql/backups/2023-08-22

如果你不想保留备份,可以使用--move-back选项,它将备份的数据移动到数据目录。

在恢复备份之前,数据目录(datadir)必须为空。另外,需要注意的是,在执行恢复操作之前必须关闭MySQL服务器。你不能将备份恢复到正在运行的mysqld实例的数据目录中(除非在导入部分备份时)。

你应该检查恢复后的文件是否具有正确的所有权和权限。

由于文件的属性将被保留,大多数情况下,在启动数据库服务器之前,你需要将文件的所有权更改为mysql用户,因为这些文件的所有权将属于创建备份的用户:

1chown -R mysql:mysql /var/lib/mysql

数据现在已经恢复,就可以启动mysqld服务了。

3.增量备份

xtrabackup支持增量备份,这意味着它们可以复制自上次备份以来发生变化的所有数据。

注意: MyRocks存储引擎上的增量备份不会确定之前的完整备份或增量备份是否包含相同的文件。Percona XtraBackup每次进行备份时都会复制所有MyRocks文件。

你可以在每个完整备份之间执行多次增量备份,因此你可以设置一个备份流程,例如每周进行一次完整备份,每天进行一次增量备份,或者每天进行一次完整备份,每小时进行一次增量备份。

增量备份的原理是每个InnoDB页面都包含一个日志序列号(LSN)。LSN是整个数据库的系统版本号。每个页面的LSN显示了它的最近更改时间。

增量备份会复制每个页面,其LSN较新于上一个增量备份或完整备份的LSN。算法会找到满足条件的页面,并读取数据页面并检查页面的LSN。

3.1 创建一个增量备份

要创建增量备份,像往常一样从完整备份开始。xtrabackup会将一个名为xtrabackup_checkpoints的文件写入备份的目标目录中。该文件包含一行显示to_lsn,即备份结束时数据库的LSN。使用以下命令创建完整备份:

1xtrabackup --defaults-file=/etc/my.cnf --backup \
2        --user=bkpuser --password --host=localhost --port=3306 \
3        --use-memory=1GB --rsync \
4        --target-dir=/home/mysql/backups/2023-08-22

如果你查看xtrabackup_checkpoints文件,你应该会看到类似的内容,具体内容会根据你的LSN 编号而变化:

1backup_type = full-backuped
2from_lsn = 0
3to_lsn = 33431096
4last_lsn = 33431096
5flushed_lsn = 33431096
6redo_memory = 0
7redo_frames = 0

现在你已经拥有了一个完整的备份,你可以基于它创建一个增量备份。使用以下命令:

1xtrabackup --defaults-file=/etc/my.cnf --backup \
2        --user=bkpuser --password --host=localhost --port=3306 \
3        --use-memory=1GB --rsync \
4        --target-dir=/home/mysql/backups/2023-08-22_inc1 \
5        --incremental-basedir=/home/mysql/backups/2023-08-22

现在,/home/mysql/backups/2023-08-22_inc1 目录应该包含增量文件,例如 ibdata1.deltatest/table1.ibd.delta。这些文件表示从LSN 33431096 开始的更改。如果你检查该目录中的 xtrabackup_checkpoints 文件,你应该会看到类似以下内容的信息:

1backup_type = incremental
2from_lsn = 33431096
3to_lsn = 33431992
4last_lsn = 33431992
5flushed_lsn = 33431992
6redo_memory = 0
7redo_frames = 0

from_lsn 是备份的起始LSN,对于增量备份,它必须与前一个基本备份的 to_lsn(如果是上一个检查点的最后一个 LSN)相同。

现在,你可以将此目录作为另一个增量备份的基础目录:

1xtrabackup --defaults-file=/etc/my.cnf --backup \
2        --user=bkpuser --password --host=localhost --port=3306 \
3        --use-memory=1GB --rsync \
4        --target-dir=/home/mysql/backups/2023-08-22_inc2 \
5        --incremental-basedir=/home/mysql/backups/2023-08-22_inc1

备份后/home/mysql/backups/2023-08-22_inc2这个文件夹还包含了xtrabackup_checkpoints文件:

1backup_type = incremental
2from_lsn = 33431992
3to_lsn = 33435246
4last_lsn = 33435246
5flushed_lsn = 33435246
6redo_memory = 0
7redo_frames = 0

下一步是准备备份,以便进行还原。

3.2 准备增量备份

增量备份的--prepare步骤与完全备份不同。在完全备份中,为了使数据库一致,执行两种类型的操作:已提交的事务从日志文件中重新执行到数据文件,未提交的事务被回滚。在准备增量备份时,必须跳过未提交事务的回滚操作,因为在备份时未提交的事务可能正在进行中,并且很可能会在下一个增量备份中被提交。你应该使用--apply-log-only选项来防止回滚阶段的执行。

如果你不使用--apply-log-only选项来防止回滚阶段的执行,那么你的增量备份将是无用的。在事务被回滚后,将无法应用进一步的增量备份。

从你创建的完整备份开始,你可以准备它,然后将增量差异应用于它。查看一下各个备份目录:

1du -sh /home/mysql/backups/*
289M     /home/mysql/backups/2023-08-22
32.1M    /home/mysql/backups/2023-08-22_inc1
42.3M    /home/mysql/backups/2023-08-22_inc2

要准备基本备份,你需要像往常一样运行--prepare命令,但是要通过--apply-log-only阻止回滚阶段:

1xtrabackup --prepare --apply-log-only --target-dir=/home/mysql/backups/2023-08-22

输出的末尾应该类似于以下内容:

1InnoDB: Shutdown completed; log sequence number 33431106
2161011 12:41:04 completed OK!

日志序列号应该与之前所看到的基本备份的to_lsn匹配。

警告: 即使跳过了回滚阶段,此备份现在实际上是可以安全恢复的。如果你恢复它并启动MySQL,InnoDB将检测到回滚阶段未执行,它会在后台执行回滚阶段,就像在启动时进行崩溃恢复一样。它会通知你数据库未正常关闭。

要将第一个增量备份应用到完整备份中,请运行以下命令:

1xtrabackup --prepare --apply-log-only --target-dir=/home/mysql/backups/2023-08-22 \
2--incremental-dir=/home/mysql/backups/2023-08-22_inc1

这将增量文件应用于 /home/mysql/backups/2023-08-22 目录中的文件,将它们向前滚动到增量备份的时间。然后按通常的方式应用redo日志到结果中。最终的数据位于 /home/mysql/backups/2023-08-22 目录中,而不在增量目录中。

Percona XtraBackup不支持使用同一个增量备份目录来准备两个备份副本。请勿多次使用相同的增量备份目录(即--incremental-dir的值)运行 –prepare。

准备第二个增量备份的过程类似:将增量变更应用于(修改后的)基本备份,然后将其数据向前滚动到第二个增量备份的时间点:

1xtrabackup --prepare --target-dir=/home/mysql/backups/2023-08-22 \
2--incremental-dir=/home/mysql/backups/2023-08-22_inc2

注: 2023-08-22_inc2是用于还原的最后一个增量备份,因此不加--apply-log-only。在合并增量备份时,除了最后一个备份外,都应使用--apply-log-only选项。。即使在最后一步使用--apply-log-only,备份仍然是一致的,但在这种情况下,服务器将执行回滚阶段。

3.3 还原增量备份

准备好的增量备份与完整备份相同,可以使用和之前全量备份还原相同的方式进行恢复。

1xtrabackup --copy-back --target-dir=/home/mysql/backups/2023-08-22

由于文件的属性将被保留,大多数情况下,在启动数据库服务器之前,你需要将文件的所有权更改为mysql用户,因为这些文件的所有权将属于创建备份的用户:

1chown -R mysql:mysql /var/lib/mysql

数据现在已经恢复,就可以启动mysqld服务了。

参考