搭建mysql从库的一般步骤及 XtraBackup 8.0 中有可能导致主从复制

2022-06-06 19:45:20 浏览数 (2)

搭建从库,本质上需要的只是一个一致性备份集及这个备份集对应的位置点信息。之前介绍的几个备份工具( MySQL中如何选择合适的备份策略和备份工具 )均可满足。

这里,我们重点看看如何基于 XtraBackup 搭建从库。

整个过程其实比较简单,无非是备份还原。唯一需要注意的是建立复制时位置点的选择,包括:

  1. 在基于位置点的复制中,CHANGE MASTER TO 语句中 MASTER_LOG_FILE 和 MASTER_LOG_POS 的选择。
  2. 在 GTID 复制中,在执行 CHANGE MASTER TO 命令之前,必须首先设置 GTID_PURGED。

尤其是在 MySQL 8.0 中,得益于 performance_schema.log_status 的引入( 注意,不是备份锁 ),XtraBackup 8.0 在备份的过程中不再加全局读锁。

而备份集对应的位置点信息,是 XtraBackup 8.0 在备份结束时查询 performance_schema.log_status 获取的,包括 GTID 和 Binlog 的位置点。

理论上,备份集里保存的 GTID 和 Binlog 位置点,指向的应该是同一个事务。

但在 XtraBackup 8.0 中,却并非如此。

由此带来的问题是,在 GTID 复制中,如果我们还是按照 MySQL 5.6,5.7( 对应 XtraBackup 2.4 )中的方法来搭建从库,大概率会导致主从数据不一致,甚至主从复制中断。

So,在 XtraBackup 8.0 中,我们又该如何搭建从库呢?

本文主要包括以下几部分:

  1. 使用 XtraBackup 搭建从库的一般步骤。
  2. 基于从库备份搭建从库时的注意事项。
  3. GTID 复制中,为什么需要设置 GTID_PURGED?
  4. 设置 GTID_PURGED 时的注意事项。
  5. 使用 XtraBackup 8.0 搭建从库时的注意事项。
  6. performance_schema.log_status 的作用。
  7. XtraBackup 8.0 中哪些场景会加全局读锁?

使用 XtraBackup 搭建从库的一般步骤

以下是测试环境信息。

角色

IP地址

主库

10.0.0.118

从库

10.0.0.195

下面我们看看具体的搭建步骤。

1. 主库上创建复制账号

代码语言:javascript复制
mysql> create user 'repl'@'%' identified by 'repl123';
Query OK, 0 rows affected (0.01 sec)

mysql> grant replication slave on *.* TO 'repl'@'%';
Query OK, 0 rows affected (0.00 sec)

2. 对主库进行备份

在 10.0.0.118 上执行备份命令。

代码语言:javascript复制
# xtrabackup --user=backup_user --password=backup_pass --socket=/data/mysql/3306/data/mysql.sock --backup --parallel=10 --slave-info --target-dir=/data/backup/full

3. 将备份文件传输到从库上

代码语言:javascript复制
# scp -r /data/backup/full/* root@10.0.0.195:/data/backup/full

4. 从库上准备好 MySQL 安装包及参数文件

代码语言:javascript复制
# tar xvf mysql-8.0.27-linux-glibc2.12-x86_64.tar.xz -C /usr/local/
# cd /usr/local/
# ln -s mysql-8.0.27-linux-glibc2.12-x86_64 mysql

5. 在从库上进行 Prepare 和恢复

代码语言:javascript复制
# xtrabackup --prepare --target-dir=/data/backup/full
# xtrabackup --defaults-file=/etc/my.cnf --copy-back --parallel=10 --target-dir=/data/backup/full

恢复命令中的 /etc/my.cnf 是从库的配置文件。

其中,第 2,3,5 步可以简化为下面这两条命令。

代码语言:javascript复制
# xtrabackup 
--user=backup_user --password=backup_pass --socket=/data/mysql/3306/data/mysql.sock 
--backup --stream=xbstream --slave-info --parallel=10 | lz4 | 
ssh mysql@10.0.0.195 'cat - | lz4 -d | xbstream -p10 -x -C /data/mysql/3306/data/'
# xtrabackup --prepare --target-dir=/data/mysql/3306/data/

第一条命令是线上搭建从库时的一条常用命令,它将流式备份、管道结合在一起,具有以下优点:

  1. 边备份,边解压。相对于备份、传输、再解压,花费的时间更短。
  2. 备份集是直接解压到从库服务器,并不会保存到本地。这样,对于主库服务器,一可减少磁盘空间,二可减小磁盘 IO 压力。
  3. /data/mysql/3306/data/ 是从库的数据目录,在恢复时,无需 --copy-back,直接 Prepare 即可。

6. 启动实例

代码语言:javascript复制
# chown -R mysql.mysql /data/mysql/3306/data/
# /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf &

很多人有个误区,认为搭建从库,需要提前创建个空白实例。对于逻辑备份确实如此,但对于物理备份,则无此必要,直接使用 mysqld_safe 启动还原后的备份文件即可。

7. 建立复制

这里需要区分两种场景:GTID 复制和基于位置点的复制。

首先查看备份集中的xtrabackup_binlog_info 文件的内容。

代码语言:javascript复制
# cat xtrabackup_binlog_info
mysql-bin.000002 882880068 2cbdc21a-db11-11ec-83bf-020017003dc4:1-223148

如果 xtrabackup_binlog_info 中存在 GTID 信息,则代表备份实例开启了 GTID,这个时候就需要建立 GTID 复制。

7.1 GTID 复制

对于 GTID 复制,在建立复制前,必须首先设置 GTID_PURGED。

设置 GTID_PURGED 时,注意备份实例的版本。

MySQL 5.7

在 MySQL 5.7 中,因为引入了 mysql.gtid_executed。

从库实例启动后,会基于该表的值来初始化 GTID_EXECUTED 和 GTID_PURGED。

代码语言:javascript复制
mysql> select * from mysql.gtid_executed;
 -------------------------------------- ---------------- -------------- 
| source_uuid                          | interval_start | interval_end |
 -------------------------------------- ---------------- -------------- 
| 2cbdc21a-db11-11ec-83bf-020017003dc4 |              1 |         2124 |
 -------------------------------------- ---------------- -------------- 
1 row in set (0.00 sec)

mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged');
 --------------- --------------------------------------------- 
| Variable_name | Value                                       |
 --------------- --------------------------------------------- 
| gtid_executed | 2cbdc21a-db11-11ec-83bf-020017003dc4:1-2124 |
| gtid_purged   | 2cbdc21a-db11-11ec-83bf-020017003dc4:1-2124 |
 --------------- --------------------------------------------- 
2 rows in set (0.00 sec)

但很明显,GTID_PURGED 与 xtrabackup_binlog_info 中的 GTID 信息相差甚远。

关于这一点,不难理解,因为主库的 mysql.gtid_executed,在 MySQL 8.0.17 之前,只有在日志切换和实例关闭时更新。

下面我们基于 xtrabackup_binlog_info 中的 GTID 信息重新设置 GTID_PURGED。

代码语言:javascript复制
mysql> reset master;
Query OK, 0 rows affected (0.00 sec)

mysql> set global gtid_purged='2cbdc21a-db11-11ec-83bf-020017003dc4:1-223148';
Query OK, 0 rows affected (0.01 sec)

因为 GTID_EXECUTED 有值,所以在设置 GTID_PURGED 之前,必须首先通过 RESET MASTER 命令清空 GTID_EXECUTED。

MySQL 5.6

可直接基于 xtrabackup_binlog_info 中的 GTID 信息设置 GTID_PURGED。

代码语言:javascript复制
mysql> set global gtid_purged='2cbdc21a-db11-11ec-83bf-020017003dc4:1-223148';

为什么在 MySQL 5.6 中无需执行 RESET MASTER 呢?

因为 MySQL 5.6 中还没有引入 mysql.gtid_executed,实例恢复后,GTID_EXECUTED 和 GTID_PURGED 均为空。

MySQL 8.0

在 MySQL 8.0 中,无需设置 GTID_PURGED。

至于为什么不用设置,后面会有详细介绍。这里,大家记住这个结论就可以了。

设置完 GTID_PURGED,接下来执行 CHANGE MASTER TO 命令。

代码语言:javascript复制
CHANGE MASTER TO
  MASTER_HOST='10.0.0.118',
  MASTER_USER='repl',
  MASTER_PASSWORD='repl123',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION = 1;

对于 GTID 复制,需将 MASTER_AUTO_POSITION 设置为 1。

在 MySQL 8.0 中,CHANGE MASTER TO 语句中还需添加 GET_MASTER_PUBLIC_KEY = 1。

7.2 基于位置点的复制

如果 xtrabackup_binlog_info 没有 GTID 信息,则代表备份实例没有开启 GTID,这个时候就无需设置 GTID_PURGED,直接执行 CHANGE MASTER TO 命令即可。

代码语言:javascript复制
CHANGE MASTER TO
  MASTER_HOST='10.0.0.118',
  MASTER_USER='repl',
  MASTER_PASSWORD='repl123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000002',
  MASTER_LOG_POS=882880068;

CHANGE MASTER TO 语句中的 MASTER_LOG_FILE 和 MASTER_LOG_POS 的值分别取自 xtrabackup_binlog_info 中的 filename 和 position。

8. 开启复制

代码语言:javascript复制
mysql> start slave;

9. 检查主从复制是否正常

代码语言:javascript复制
mysql> show slave statusG

Slave_IO_Running 和 Slave_SQL_Running 均为 Yes 代表复制正常。

以上就是使用 XtraBackup 搭建从库的基本步骤。

基于从库备份搭建从库时的注意事项

不过在线上,我们很少会对主库进行备份,一般是备份从库。所以,基于从库的备份来搭建一个新的从库是一个更为常见的场景。

对于这种场景,上面的搭建步骤同样适用,不过有以下几点需要注意:

1. 对从库进行备份,需指定 --slave-info。这个时候备份集中会生成一个 xtrabackup_slave_info 文件,该文件记录了备份时备份实例对应主库的一致性位置点信息,如,

代码语言:javascript复制
# cat xtrabackup_slave_info 
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=6263314;

如果从库开启了 GTID,则只会记录 GTID 信息,如,

代码语言:javascript复制
SET GLOBAL gtid_purged='2cbdc21a-db11-11ec-83bf-020017003dc4:1-2049780';
CHANGE MASTER TO MASTER_AUTO_POSITION=1;

其实,对主库备份,也可指定 --slave-info,只不过此时的 xtrabackup_slave_info 内容为空。

所以,上面搭建步骤中的备份命令都带上了 --slave-info。

2. 在基于位置点的复制中,CHANGE MASTER TO 语句中的 MASTER_LOG_FILE 和 MASTER_LOG_POS 必须取自 xtrabackup_slave_info,而不是 xtrabackup_binlog_info。

对于 GTID 复制,则没关系,因为 xtrabackup_slave_info 和 xtrabackup_binlog_info 中的 GTID 信息是一致的。

3. 只要是基于从库的备份来搭建从库,在执行 CHANGE MASTER TO 之前,都必须首先执行 RESET SLAVE ALL 清空 mysql.slave_master_info 和 mysql.slave_relay_log_info 表中的内容。

设置 GTID_PURGED 时的注意事项

在 GTID 复制中,为什么需要设置 GTID_PURGED 呢?

实际上,设置 GTID_PURGED 只是手段,最终目的还是为了设置 GTID_EXECUTED。

GTID_EXECUTED

GTID_EXECUTED 代表了实例中已经执行过的 GTID 集。在建立复制后,从库会自动跳过 GTID_EXECUTED 相关的事务。如果这个值设置不准确,会导致事务丢失,或者已经重放过的操作重复执行。

但 GTID_EXECUTED 是个只读参数,不能直接修改。

代码语言:javascript复制
mysql> set global gtid_executed='411693c9-d512-11ec-9e11-525400d51a16:1-10369';
ERROR 1238 (HY000): Variable 'gtid_executed' is a read only variable

如果我们要修改它,必须通过修改 GTID_PURGED 来间接修改它。

GTID_PURGED

GTID_PURGED 代表了实例中已经执行过,但 Binlog 中不存在的 GTID 集。所以 GTID_PURGED 一定是 GTID_EXECUTED 的子集。

在 MySQL 8.0 之前,如果要修改 GTID_PURGED,GTID_EXECUTED 必须为空。

代码语言:javascript复制
mysql> set global gtid_purged='411693c9-d512-11ec-9e11-525400d51a16:1-10369';
ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

而要 GTID_EXECUTED 为空,只能执行 RESET MASTER 操作。

代码语言:javascript复制
mysql> reset master;
Query OK, 0 rows affected (0.02 sec)

mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged');
 --------------- ------- 
| Variable_name | Value |
 --------------- ------- 
| gtid_executed |       |
| gtid_purged   |       |
 --------------- ------- 
2 rows in set (0.00 sec)

mysql> set global gtid_purged='411693c9-d512-11ec-9e11-525400d51a16:1-10369';
Query OK, 0 rows affected (0.00 sec)

mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged');
 --------------- ---------------------------------------------- 
| Variable_name | Value                                        |
 --------------- ---------------------------------------------- 
| gtid_executed | 411693c9-d512-11ec-9e11-525400d51a16:1-10369 |
| gtid_purged   | 411693c9-d512-11ec-9e11-525400d51a16:1-10369 |
 --------------- ---------------------------------------------- 
2 rows in set (0.00 sec)

可以看到,调整完 GTID_PURGED 后,GTID_EXECUTED 也随之更改。

在 MySQL 8.0 中,则剔除了这一限制,即设置 GTID_PURGED 时,无需 GTID_EXECUTED 为空。但也不能随便设置,设置时需满足以下要求:

1.  设置的 GTID_PURGED 不能与 gtid_subtract(@@gtid_executed, @@gtid_purged) 存在交集。

看下面这个示例。

代码语言:javascript复制
mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged');
 --------------- ------------------------------------------ 
| Variable_name | Value                                    |
 --------------- ------------------------------------------ 
| gtid_executed | a028d418-ccce-11ec-bf07-525400d51a16:1-8 |
| gtid_purged   | a028d418-ccce-11ec-bf07-525400d51a16:1-4 |
 --------------- ------------------------------------------ 
2 rows in set (0.00 sec)

mysql> select gtid_subtract(@@gtid_executed, @@gtid_purged);
 ----------------------------------------------- 
| gtid_subtract(@@gtid_executed, @@gtid_purged) |
 ----------------------------------------------- 
| a028d418-ccce-11ec-bf07-525400d51a16:5-8      |
 ----------------------------------------------- 
1 row in set (0.00 sec)

mysql> set global gtid_purged='a028d418-ccce-11ec-bf07-525400d51a16:1-5';
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED

2.  设置的 GTID_PURGED 必须是当前 GTID_PURGED 的超集。

代码语言:javascript复制
mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged');
 --------------- ------------------------------------------ 
| Variable_name | Value                                    |
 --------------- ------------------------------------------ 
| gtid_executed | a028d418-ccce-11ec-bf07-525400d51a16:1-8 |
| gtid_purged   | a028d418-ccce-11ec-bf07-525400d51a16:1-4 |
 --------------- ------------------------------------------ 
2 rows in set (0.00 sec)

mysql> set global gtid_purged='a028d418-ccce-11ec-bf07-525400d51a16:1-3';
ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the new value must be a superset of the old value

mysql> set global gtid_purged='a028d418-ccce-11ec-bf07-525400d51a16:1-4,9b481834-de85-11ec-9045-020017003dc4:1-10';
Query OK, 0 rows affected (0.01 sec)

mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged')G
*************************** 1. row ***************************
Variable_name: gtid_executed
        Value: 9b481834-de85-11ec-9045-020017003dc4:1-10,
a028d418-ccce-11ec-bf07-525400d51a16:1-8
*************************** 2. row ***************************
Variable_name: gtid_purged
        Value: 9b481834-de85-11ec-9045-020017003dc4:1-10,
a028d418-ccce-11ec-bf07-525400d51a16:1-4
2 rows in set (0.00 sec)

可以看到,新添加的 GTID 集同样也添加到 GTID_EXECUTED 中了。

除了直接指定,在 MySQL 8.0 中还支持通过 号添加新的 GTID 集。如,

代码语言:javascript复制
mysql> set global gtid_purged=' 9b481834-de85-11ec-9045-020017003dc4:1-10';
Query OK, 0 rows affected (0.01 sec)

使用 XtraBackup 8.0 搭建从库时的注意事项

XtraBackup 8.0 中没有加全局读锁,备份结束时的位置点信息查询的是 performance_schema.log_status。

该表的内容如下,

代码语言:javascript复制
mysql> select * from performance_schema.log_statusG
*************************** 1. row ***************************
    SERVER_UUID: d310871c-db0c-11ec-a557-020017003dc4
          LOCAL: {"gtid_executed": "d310871c-db0c-11ec-a557-020017003dc4:1-352559", "binary_log_file": "mysql-bin.000022", "binary_log_position": 9698237}
    REPLICATION: {"channels": []}
STORAGE_ENGINES: {"InnoDB": {"LSN": 912297234, "LSN_checkpoint": 912297234}}
1 row in set (0.00 sec)

需要注意的是,LOCAL 中的 gtid_executed 和 binary_log_file binary_log_position 对应的并不总是同一个事务。

这一点很容易模拟出来,对一张表持续进行插入操作即可。

下面我们看一个具体的案例。

备份过程中,持续对一张表进行插入操作。最后备份集中 xtrabackup_binlog_info 的内容如下。

代码语言:javascript复制
# cat xtrabackup_binlog_info
mysql-bin.000024 507 d310871c-db0c-11ec-a557-020017003dc4:1-388482

接下来我们基于 Binlog 的位置点信息 "mysql-bin.000024 507" 查找对应的事务。

代码语言:javascript复制
# mysqlbinlog -v --base64-output=decode-rows --stop-position=507 mysql-bin.000024
# The proper term is pseudo_replica_mode, but we use this compatibility alias
# to make the statement usable on server versions 8.0.24 and older.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#220529 11:19:07 server id 1  end_log_pos 126 CRC32 0xdcc54ec7  Start: binlog v 4, server v 8.0.28 created 220529 11:19:07
# at 126
#220529 11:19:07 server id 1  end_log_pos 197 CRC32 0x5d440f7c  Previous-GTIDs
# d310871c-db0c-11ec-a557-020017003dc4:1-388482
# at 197
#220529 11:19:07 server id 1  end_log_pos 276 CRC32 0x0dd893b5  GTID last_committed=0 sequence_number=1 rbr_only=yes original_committed_timestamp=1653823147539722 immediate_commit_timestamp=1653823147539722 transaction_length=310
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
# original_commit_timestamp=1653823147539722 (2022-05-29 11:19:07.539722 GMT)
# immediate_commit_timestamp=1653823147539722 (2022-05-29 11:19:07.539722 GMT)
/*!80001 SET @@session.original_commit_timestamp=1653823147539722*//*!*/;
/*!80014 SET @@session.original_server_version=80028*//*!*/;
/*!80014 SET @@session.immediate_server_version=80028*//*!*/;
SET @@SESSION.GTID_NEXT= 'd310871c-db0c-11ec-a557-020017003dc4:388483'/*!*/;
# at 276
#220529 11:19:07 server id 1  end_log_pos 365 CRC32 0xa49dc290  Query thread_id=262 exec_time=0 error_code=0
...
BEGIN
/*!*/;
# at 365
#220529 11:19:07 server id 1  end_log_pos 425 CRC32 0x824f6309  Table_map: `slowtech`.`t1` mapped to number 157
# at 425
#220529 11:19:07 server id 1  end_log_pos 476 CRC32 0x5a6fe6ec  Write_rows: table id 157 flags: STMT_END_F
### INSERT INTO `slowtech`.`t1`
### SET
###   @1=1483132
###   @2='aaaaaaaaaa'
# at 476
#220529 11:19:07 server id 1  end_log_pos 507 CRC32 0x66a401f6  Xid = 4108904
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

可以看到,该事务对应的 GTID 是 d310871c-db0c-11ec-a557-020017003dc4:388483,不是 xtrabackup_binlog_info 中的 388482。

如果我们像在 MySQL 5.6,5.7 中那样,基于 xtrabackup_binlog_info 中的 GTID 信息来设置 GTID_PURGED,在我们这个 case 中,会导致同一个 INSERT 操作执行两次,进而会出现主键冲突,主从复制中断。

如此来看,问题的根源还是出在 performance_schema.log_status 中的 gtid_executed 和 binary_log_file binary_log_position 指向的不是同一个事务。

这是一个 Bug 吗?其实不然。

XtraBackup 8.0 在查询完 performance_schema.log_status 后,会基于查询到的 binary_log_file 和 binary_log_position 拷贝对应的 Binlog 。

下面是备份集中拷贝的 Binlog。

代码语言:javascript复制
# ll /data/backup/full/
...
-rw-r-----. 1 root root      507 May 29 11:19 mysql-bin.000024
-rw-r-----. 1 root root       19 May 29 11:19 mysql-bin.index
...

Binlog 中记录了 "mysql-bin.000024 507" 这个位置点的事务所对应的 GTID 值。

实例启动时,会自动基于 Binlog 中的 GTID 信息来初始化 GTID_EXECUTED 和 GTID_PURGED。

代码语言:javascript复制
mysql> show global variables where variable_name in ('gtid_executed', 'gtid_purged');
 --------------- ----------------------------------------------- 
| Variable_name | Value                                         |
 --------------- ----------------------------------------------- 
| gtid_executed | d310871c-db0c-11ec-a557-020017003dc4:1-388483 |
| gtid_purged   | d310871c-db0c-11ec-a557-020017003dc4:1-388482 |
 --------------- ----------------------------------------------- 
2 rows in set (0.00 sec)

所以,实例起来后,我们看到的 GTID_EXECUTED 就已经是正确值,就已经能正确反映备份结束时的一致性位置点信息了。

这个时候,直接执行 CHANGE MASTER TO 操作就可以了。

performance_schema.log_status 的作用

关于 performance_schema.log_status 的作用,其实官方文档中也提到了,是提供位置点信息,供备份工具拷贝所需的 Binlog。查询的过程中也会阻塞日志和相关管理操作。不过阻塞的时间很短,填充完表中的数据就会释放资源。

代码语言:javascript复制
The log_status table provides information that enables an online backup tool to copy the required log files without locking those resources for the duration of the copy process.

When the log_status table is queried, the server blocks logging and related administrative changes for just long enough to populate the table, then releases the resources. 

The log_status table informs the online backup which point it should copy up to in the source's binary log and gtid_executed record, and the relay log for each replication channel. 

It also provides relevant information for individual storage engines, such as the last log sequence number (LSN) and the LSN of the last checkpoint taken for the InnoDB storage engine.

XtraBackup 8.0 中哪些场景会加全局读锁

下面两种场景,XtraBackup 8.0 会加全局读锁:

  1. 备份实例中存在 MyISAM 表。
  2. 备份从库,且命令行中指定了 --slave-info,且从库 SHOW SLAVE STATUS 中的 Auto_Position 不为 1。 Auto_Position 不为 1 意味着从库没有开启 GTID 复制,或者开启了 GTID 复制,但未将 MASTER_AUTO_POSITION 设置为 1。

总结

1. 备份锁引入的初衷是为了阻塞备份过程中的 DDL,不是为了替代全局读锁。在 XtraBackup 8.0 中,我们可以指定 --skip-lock-ddl 禁用备份锁,这并不影响 XtraBackup 的正常使用。

2. 基于物理备份搭建从库时,无需提前创建空白实例。

3. 在基于位置点的复制中,注意 CHANGE MASTER TO 语句中 MASTER_LOG_FILE 和 MASTER_LOG_POS 的选择。

以一个简单的主从复制拓扑为例:master -> slave1。

  • 如果是基于 master 的备份添加一个 master 的从库,或者,基于 slave1 的备份添加一个 slave1 的从库。建立复制时,应使用 xtrabackup_binlog_info 的位置点信息。
  • 如果是基于 slave1 的备份添加 master 的一个从库,应使用 xtrabackup_slave_info 的位置点信息。

4. 基于从库的备份搭建从库时,在执行 CHANGE MASTER TO 操作之前,必须首先执行 RESET SLAVE ALL。

5. 无论是对主库还是从库进行备份,都可指定  --slave-info,此时都会生成 xtrabackup_slave_info。只不过如果是对主库进行备份,该文件会为空。

6. 在 GTID 复制中,设置 GTID_PURGED 时,注意备份实例的版本。如果是 MySQL 5.6,5.7,可直接基于 xtrabackup_binlog_info 中的 GTID 信息设置 GTID_PURGED。如果是 MySQL 8.0,无需再设置 GTID_PURGED。

0 人点赞