了解这个MySQL 8.0新特性,添加节点一条命令搞定

陈臣 2022-07-04 09:19:13
作者介绍

陈臣,甲骨文MySQL首席解决方案工程师,公众号《MySQL实战》作者,有大规模的MySQL,Redis,MongoDB,ES的管理和维护经验,擅长MySQL数据库的性能优化及日常操作的原理剖析。

 

Clone Plugin(克隆插件)是MySQL 8.0.17引入的一个重大特性,实现该特性主要是为Group Replication服务。在Group Replication中,如果要添加一个新的节点,这个节点差异数据的补齐是通过分布式恢复(Distributed Recovery)来实现的。

 

在MySQL 8.0.17之前,只支持一种恢复方式,即Binlog。如果新节点需要的Binlog在集群中不存在,那么就只能借助于备份工具先做个全量数据的备份恢复,再通过分布式恢复同步增量数据。

 

这种方式虽然也能达到添加节点的目的,但总归是要借助外部工具,相对来说有一定的使用门槛和工作量。

 

有了Clone Plugin,只用一条命令,我们就能很方便地添加一个新的节点,无论是在Group Replication还是普通的主从环境中。

 

一、Clone Plugin的安装

 

Clone Plugin可通过以下两种方式安装:

 

1)配置文件中指定

 

[mysqld]

plugin-load-add=mysql_clone.so

 

2)动态加载

 

mysql> install plugin clone soname 'mysql_clone.so';

 

执行show plugins查看插件是否安装成功。

 

mysql> show plugins;

+---------------------------------+----------+--------------------+----------------+---------+

| Name                            | Status   | Type               | Library        | License |

+---------------------------------+----------+--------------------+----------------+---------+

...

| clone                           | ACTIVE   | CLONE              | mysql_clone.so | GPL     |

...

 

Status为ACTIVE代表插件加载成功。

 

二、Clone Plugin的使用

 

Clone Plugin支持两种克隆方式:本地克隆和远程克隆。这两种克隆方式的使用方法如下。

 

 
1、本地克隆

 

本地克隆的原理图如下所示,它可将本地MySQL实例中的数据拷贝到本地服务器的一个目录中。本地克隆只能在实例本地发起。

 

 

本地克隆命令的语法如下:

 

CLONE LOCAL DATA DIRECTORY [=] 'clone_dir';

 

下面我们看下具体的使用步骤:

 

1)创建克隆用户

 

mysql> create user 'clone_user'@'%' identified by 'clone_pass';

mysql> grant backup_admin on *.* to 'clone_user'@'%';

 

这里的backup_admin是克隆操作必需权限,它允许用户执行LOCK INSTANCE FOR BACKUP命令。

 

2)创建克隆目录

 

# mkdir -p /data/backup

# chown -R mysql.mysql /data/backup/

 

3)执行本地克隆操作

 

# mysql -uclone_user -pclone_pass

mysql> clone local data directory='/data/backup/3307';

 

这里的/data/backup/3307是克隆目录,它需满足以下几点要求:

 

  • 克隆目录必须是绝对路径。

  • /data/backup必须存在,且MySQL对其有可写权限。

  • 最后一级目录3307不能存在。

 

4)查看克隆目录的内容

 

# ll /data/backup/3307

total 200644

drwxr-x--- 2 mysql mysql       89 Oct 23 22:09 #clone

-rw-r----- 1 mysql mysql     4049 Oct 23 22:09 ib_buffer_pool

-rw-r----- 1 mysql mysql 12582912 Oct 23 22:09 ibdata1

-rw-r----- 1 mysql mysql 50331648 Oct 23 22:09 ib_logfile0

-rw-r----- 1 mysql mysql 50331648 Oct 23 22:09 ib_logfile1

drwxr-x--- 2 mysql mysql        6 Oct 23 22:09 mysql

-rw-r----- 1 mysql mysql 25165824 Oct 23 22:09 mysql.ibd

drwxr-x--- 2 mysql mysql       20 Oct 23 22:09 slowtech

drwxr-x--- 2 mysql mysql       28 Oct 23 22:09 sys

-rw-r----- 1 mysql mysql 33554432 Oct 23 22:09 undo_001

-rw-r----- 1 mysql mysql 16777216 Oct 23 22:09 undo_002

 

5)可直接基于备份集启动实例

 

# /usr/local/mysql/bin/mysqld --no-defaults --datadir=/data/backup/3307 --user mysql --port 3307 &

 

相对于Xtrabackup,Clone Plugin无需Prepare阶段。

 

 
2、远程克隆

 

远程克隆的原理图如下所示,涉及两个实例。其中,被克隆的实例是Donor,接受克隆数据的实例是Recipient。克隆命令需在Recipient上发起。

 

 

远程克隆命令的语法如下:

 

CLONE INSTANCE FROM 'user'@'host':port

IDENTIFIED BY 'password'

[DATA DIRECTORY [=] 'clone_dir']

[REQUIRE [NO] SSL];

 

其中,

 

  • host,port:被克隆实例(Donor)的 IP 和端口。

 

  • user,password:Donor 上的克隆用户和密码,需要 backup_admin 权限。

 

  • DATA DIRECTORY:备份目录。不指定的话,则默认克隆到 Recipient 的数据目录下。

 

  • REQUIRE [NO] SSL:是否开启 SSL 通信。

 

下面我们看看具体的使用步骤:

 

1)在Donor实例上创建克隆用户,加载Clone Plugin

 

mysql> create user 'donor_user'@'%' identified by 'donor_pass';

mysql> grant backup_admin on *.* to 'donor_user'@'%';

mysql> install plugin clone soname 'mysql_clone.so';

 

2)在Recipient实例上创建克隆用户,加载Clone Plugin

 

mysql> create user 'recipient_user'@'%' identified by 'recipient_pass';

mysql> grant clone_admin on *.* to 'recipient_user'@'%';

mysql> install plugin clone soname 'mysql_clone.so';

 

这里的clone_admin,隐式含有backup_admin和shutdown(重启实例)权限。

 

3)在Recipient实例上设置Donor白名单,Recipient只能克隆白名单中的实例

 

mysql> set global clone_valid_donor_list = '192.168.244.10:3306';

 

设置该参数需要SYSTEM_VARIABLES_ADMIN权限。

 

4)在Recipient上发起克隆命令

 

# mysql -urecipient_user -precipient_pass

mysql> clone instance from 'donor_user'@'192.168.244.10':3306 identified by 'donor_pass';

远程克隆会依次执行以下操作:

 

  • 获取备份锁 (Backup Lock)。备份锁和DDL互斥。注意,获取的不仅仅的是Recipient上的备份锁,Donor上的同样也要获取。

 

  • Drop用户表空间。注意,Drop的只是用户表空间,不是数据目录,也不包括ib_buffer_pool、ibdata等系统文件。

 

  • 从Donor实例拷贝数据。对于用户表空间,会直接拷贝。对于系统文件 ,则会重命名为xxx.#clone,不会直接替代原文件。如:

 

# ll /data/mysql/3306/data/

...

-rw-r----- 1 mysql mysql      4049 Oct 24 09:11 ib_buffer_pool

-rw-r----- 1 mysql mysql      4049 Oct 24 10:54 ib_buffer_pool.#clone

-rw-r----- 1 mysql mysql  12582912 Oct 24 10:55 ibdata1

-rw-r----- 1 mysql mysql  12582912 Oct 24 10:55 ibdata1.#clone

...

-rw-r----- 1 mysql mysql  25165824 Oct 24 10:55 mysql.ibd

-rw-r----- 1 mysql mysql         0 Oct 24 10:54 mysql.ibd.#clone

...

 

  • 重启实例。在启动的过程中,会用xxx.#clone替换掉原来的系统文件。

 

三、如何查看克隆操作的进度

 

查看克隆操作的进度,主要依托于performance_schema中的两张表:clone_status和clone_progress。

 

下面我们具体看看这两张表的作用及各字段的含义。

 

 
1、clone_status

 

clone_status表记录了克隆操作的状态信息。

 

mysql> select * from performance_schema.clone_status\G

*************************** 1. row ***************************

             ID: 1

            PID: 0

          STATE: Completed

     BEGIN_TIME: 2021-10-24 10:54:35.565

       END_TIME: 2021-10-24 10:57:02.382

         SOURCE: 192.168.244.10:3306

    DESTINATION: LOCAL INSTANCE

       ERROR_NO: 0

  ERROR_MESSAGE: 

    BINLOG_FILE: mysql-bin.000004

BINLOG_POSITION: 139952824

  GTID_EXECUTED: 453a5124-020e-11ec-8719-000c29f66609:1-17674

1 row in set (0.49 sec)

 

其中,

 

  • PID:Processlist ID。对应show processlist中的Id,如果要终止当前的克隆操作,可执行KILL QUERY processlist_id。

 

  • STATE:克隆操作的状态,包括:Not Started(克隆尚未开始),In Progress(克隆中),Completed(克隆成功),Failed(克隆失败)。如果是Failed状态,ERROR_MESSAGE会给出具体的报错信息。

 

  • BEGIN_TIME,END_TIME:克隆操作开始、结束时间。

 

  • SOURCE:Donor实例的地址。

 

  • DESTINATION:克隆目录。LOCAL INSTANCE代表当前实例的数据目录。

 

  • GTID_EXECUTED,BINLOG_FILE(BINLOG_POSITION):克隆操作对应的一致性位置点信息,可利用这些信息搭建从库。

 

 
2、clone_progress

 

clone_progress表记录了克隆操作的进度信息。

 

mysql> select * from performance_schema.clone_progress;

+------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+

| ID   | STAGE     | STATE     | BEGIN_TIME                 | END_TIME                   | THREADS | ESTIMATE  | DATA      | NETWORK   | DATA_SPEED | NETWORK_SPEED |

+------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+

|    1 | DROP DATA | Completed | 2021-10-24 10:54:48.395548 | 2021-10-24 10:54:58.352278 |       1 |         0 |         0 |         0 |          0 |             0 |

|    1 | FILE COPY | Completed | 2021-10-24 10:54:58.352527 | 2021-10-24 10:55:35.908919 |       2 | 616681425 | 616681425 | 616722587 |          0 |             0 |

|    1 | PAGE COPY | Completed | 2021-10-24 10:55:35.958036 | 2021-10-24 10:55:36.670272 |       2 |   7077888 |   7077888 |   7102277 |          0 |             0 |

|    1 | REDO COPY | Completed | 2021-10-24 10:55:36.671544 | 2021-10-24 10:55:37.160154 |       2 |   4372992 |   4372992 |   4373841 |          0 |             0 |

|    1 | FILE SYNC | Completed | 2021-10-24 10:55:37.160412 | 2021-10-24 10:55:39.724808 |       2 |         0 |         0 |         0 |          0 |             0 |

|    1 | RESTART   | Completed | 2021-10-24 10:55:39.724808 | 2021-10-24 10:56:55.207049 |       0 |         0 |         0 |         0 |          0 |             0 |

|    1 | RECOVERY  | Completed | 2021-10-24 10:56:55.207049 | 2021-10-24 10:57:02.382057 |       0 |         0 |         0 |         0 |          0 |             0 |

+------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+

7 rows in set (0.00 sec)

 

其中,

 

  • STAGE:一个克隆操作需经过DROP DATA,FILE COPY,PAGE COPY,REDO COPY,FILE SYNC,RESTART,RECOVERY这 7 个阶段。当前阶段结束了才会开始下个阶段。

 

  • STATE:当前阶段的状态,包括:Not Started,In Progress,Completed。

 

  • BEGIN_TIME,END_TIME:当前阶段的开始时间和结束时间。

 

  • THREADS:当前阶段使用的并发线程数。

 

  • ESTIMATE:预估的数据量。

 

  • DATA:已经拷贝的数据量。

 

  • NETWORK:通过网络传输的数据量。如果是本地克隆,该列的值为0。

 

  • DATA_SPEED,NETWORK_SPEED:当前数据拷贝速率和网络传输速率。注意,是当前值。

 

四、如何基于克隆数据搭建从库

 

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

 

 
1、GTID复制

 

对于GTID复制,无需关心具体的位置点信息,直接设置MASTER_AUTO_POSITION = 1即可。具体命令如下:

 

mysql> CHANGE MASTER TO MASTER_HOST = 'master_host_name', MASTER_PORT = master_port_num,

       ...

       MASTER_AUTO_POSITION = 1;

mysql> START SLAVE;

 

在MySQL 5.6,5.7中,通过Xtrabackup搭建从库,在建立复制之前,必须执行SET GLOBAL GTID_PURGED操作。注意,在MySQL 8.0中不要执行。

 

在Clone Plugin中则无需执行。通过克隆数据启动的实例,GTID_PURGED和GTID_EXECUTED默认已初始正确。

 

 
2、基于位置点的复制

 

具体命令如下:

 

mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status; 

mysql> CHANGE MASTER TO MASTER_HOST = 'master_host_name', MASTER_PORT = master_port_num,

       ...

       MASTER_LOG_FILE = 'master_log_name',

       MASTER_LOG_POS = master_log_pos;

mysql> START SLAVE;

 

其中,master_host_name,master_port_num是Donor实例的IP和端口。

 

master_log_name,master_log_pos 分别取自performance_schema.clone_status中的BINLOG_FILE和BINLOG_POSITION。

 

五、Clone Plugin的实现细节

 

克隆操作可细分为以下 5 个阶段:

 

[INIT] ---> [FILE COPY] ---> [PAGE COPY] ---> [REDO COPY] -> [Done]

 

下面我们看看各个阶段的具体作用:

 

1)INIT:初始化一个克隆对象。

 

2)FILE COPY:拷贝数据文件。

 

在拷贝之前,会将当前CHECKPOINT的LSN记为CLONE START LSN,同时启动Page Tracking。

 

Page Tracking会跟踪CLONE START LSN之后发生修改的页,记录这些页的tablespace ID和page ID。数据文件拷贝结束后,会将当前CHECKPOINT的LSN记为CLONE FILE END LSN。

 

3)PAGE COPY:拷贝Page Tracking中记录的页。

 

在拷贝之前,会基于tablespace ID和page ID对这些页进行排序,避免拷贝过程中的随机读写。同时,开启Redo Archiving。

 

Redo Archiving会在后台开启一个归档线程将Redo log的内容按Chunk拷贝到归档文件中。通常来说,归档线程的拷贝速度会快于Redo日志的生成速度。即使慢于,在写入新的Redo日志时,也会等待归档线程完成拷贝,不会覆盖还未拷贝的Redo日志。

 

Page Tracking中的页拷贝完毕后,会获取实例的一致性位置点信息,同时将此时的LSN记为CLONE LSN。

 

4)REDO COPY:拷贝归档文件中CLONE FILE END LSN与CLONE LSN之间的Redo日志。

 

5)Done:调用snapshot_end()销毁克隆对象。

 

六、Clone Plugin的要求和限制

 

在使用Clone Plugin时,注意以下限制:

 

1)克隆期间,会阻塞DDL。同样,DDL也会阻塞克隆命令的执行。不过从MySQL 8.0.27开始,克隆命令不会阻塞Donor上的DDL。

 

2)Clone Plugin不会拷贝Donor的配置参数。

 

3)Clone Plugin不会拷贝Donor的Binlog。

 

4)Clone Plugin只会拷贝InnoDB表的数据,对于其它存储引擎的表,只会拷贝表结构。

 

5)Donor实例中如果有表通过DATA DIRECTORY子句设置了绝对路径,在进行本地克隆时,会提示文件已存在。在进行远程克隆时,绝对路径必须存在且有可写权限。

 

6)不允许通过MySQL Router连接Donor实例。

 

7)执行CLONE INSTANCE操作时,指定的Donor端口不能为X Protocol端口。

 

除此之外,在进行远程克隆时,还有如下要求:

 

  • MySQL版本(包括小版本)必须一致。

 

  • 主机的操作系统和位数(32位,64位)必须一致。两者可基于参数version_compile_os,version_compile_machine获取。

 

  • Recipient必须有足够的磁盘空间存储克隆数据。

 

  • 字符集相关参数必须一致,具体包括:character_set_server(字符集),collation_server(校验集)和character_set_filesystem。

 

  • 参数innodb_page_size必须一致。

 

  • 无论是Donor,还是Recipient,同一时间,只能执行一个克隆操作。

 

  • Recipient需要重启,所以其必须通过mysqld_safe或systemd等进程管理工具进行管理,否则实例关闭后需手动拉起。

 

七、Clone Plugin与XtraBackup的异同

 

1)在实现上,两者都有FILE COPY和REDO COPY阶段,但Clone Plugin比XtraBackup多了一个PAGE COPY阶段。由此带来的好处是,Clone Plugin的恢复速度比XtraBackup快。

 

2)XtraBackup没有Redo Archiving特性,有可能出现未拷贝的Redo日志被覆盖的情况。

 

3)GTID下建立复制,Clone Plugin无需额外执行SET GLOBAL GTID_PURGED操作。

 

八、Clone Plugin的参数解析

 

1)clone_autotune_concurrency

 

是否自动调节克隆过程中并发线程数的数量,默认为ON ,此时,最大线程数由参数 clone_max_concurrency控制。若设置为OFF ,并发线程数将是固定的,等于clone_max_concurrency。后者的默认值为16 。

 

2)clone_block_ddl

 

克隆过程中是否对Donor实例加备份锁。如果加了,则会阻塞DDL。默认为OFF,不加。该参数是MySQL 8.0.27引入的。

 

3)clone_delay_after_data_drop

 

Drop完用户表空间,等待多久才执行数据拷贝操作。引入该参数的初衷是某些文件系统(如 VxFS)是异步释放空间的。如果Drop完用户表空间,就马上执行数据拷贝操作,有可能会因为空间不足而导致克隆失败。该参数是MySQL 8.0.29引入的,默认为0,不等待。

 

4)clone_buffer_size

 

本地克隆时,中转缓冲区的大小,默认4M 。缓冲区越大,备份速度越快,相应地,对磁盘IO的压力也越大。

 

5)clone_ddl_timeout

 

克隆操作需要获取备份锁。在执行CLONE命令时,如果有DDL正在执行,则CLONE命令会被阻塞,等待获取备份锁(Waiting for backup lock)。等待的最大时长由Recipient实例上的clone_ddl_timeout决定,该参数默认为300s。如果在这个时间内还没获取到备份锁,CLONE命令会失败,且提示ERROR 3862 (HY000): Clone Donor Error: 1205 : Lock wait timeout exceeded; try restarting transaction.

 

需要注意的是,在执行DDL时,如果有CLONE命令在执行,DDL同样也会因为备份锁而阻塞,只不过,DDL操作的等待时长由lock_wait_timeout决定,该参数默认为31536000s,即365天。

 

6)clone_donor_timeout_after_network_failure

 

远程克隆时,如果出现了网络错误,克隆操作不会马上终止,而是会等待一段时间。如果在这个时间内,网络恢复了,操作会继续进行。在MySQL 8.0.24之前,等待时间是固定的5min。从MySQL 8.0.24开始,可通过clone_donor_timeout_after_network_failure设置这个时间,默认是5 min。

 

7)clone_enable_compression

 

远程克隆传输数据时,是否开启压缩。默认为OFF。开启压缩能节省网络带宽,但相应地,会增加CPU消耗。

 

8)clone_max_data_bandwidth

 

远程克隆时,可允许的最大数据拷贝速率,单位MB/s。默认为0,不限制。如果Donor的磁盘IO存在瓶颈,可通过该参数来限速。

 

注意,这里限制的只是单个线程的拷贝速率。如果是多个线程并行拷贝,实际最大拷贝速率 = clone_max_data_bandwidth * 线程数。

 

9)clone_max_network_bandwidth

 

远程克隆时,可允许的最大网络传输速率,单位MiB/s 。默认为0,不限制。如果网络带宽存在瓶颈,可通过该参数来限速。

 

10)clone_valid_donor_list

 

在Recipient上设置Donor白名单,Recipient只能克隆白名单中指定的实例。在执行克隆操作之前,必须设置该参数。

 

11)clone_ssl_ca,clone_ssl_cert,clone_ssl_key

 

SSL相关。

 

>>>>

参考资料

 

  • InnoDB: Clone local replica

    https://dev.mysql.com/worklog/task/?id=9209

  • InnoDB: Clone remote replica

    https://dev.mysql.com/worklog/task/?id=9210

  • InnoDB: Clone Replication Coordinates

    https://dev.mysql.com/worklog/task/?id=9211

  • InnoDB: Clone Remote provisioning

    https://dev.mysql.com/worklog/task/?id=11636

  • MySQL/InnoDB数据克隆插件(clone plugin)实现剖析

    https://zhuanlan.zhihu.com/p/79328512

 

作者丨陈臣
来源丨公众号:MySQL实战(ID:MySQLInAction)
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

活动预告