首页 > 数据库 > MySQL > MySQL 8 新特性之Clone Plugin
Clone Plugin是MySQL 8.0.17引入的一个重大特性,为什么要实现这个特性呢?个人感觉,主要还是为Group Replication服务。在Group Replication中,添加一个新的节点,差异数据的补齐是通过分布式恢复(Distributed Recovery)来实现的。
在MySQL 8.0.17之前,只支持一种恢复方式-Binlog。但如果新节点需要的Binlog已经被Purge了,这个时候,只能先借助于备份工具(XtraBackup,mydumper,mysqldump)做个全量数据的同步,然后再通过分布式恢复同步增量数据。
这种方式,虽然也能实现添加节点的目的,但总归还是要借助于外部工具,需要一定的工作量和使用门槛。要知道,其竞争对手,PXC,默认集成了XtraBackup进行State Snapshot Transfer(类似于全量同步),而MongoDB则更进一步,原生就实现了Initial Sync同步全量数据。从易用性来看,单就集群添加节点这一项而言,MySQL确实不如其竞争对手。客户体验上,还有很大的提升空间。
好在MySQL官方也正视到这个差距,终于在MySQL 8.0.17实现了Clone Plugin。当然,对于官方来说,实现这个特性并不算难,毕竟有现成的物理备份工具(MySQL Enterprise Backup)可供借鉴。
本文将从以下几个方面展开:
- Clone Plugin的安装
- Clone Plugin的使用
- 如何查看克隆操作的进度
- 如何基于克隆数据搭建从库
- Clone Plugin的实现细节
- Clone Plugin的限制
- Clone Plugin与XtraBackup的对比
- Clone Plugin的参数解析
Clone Plugin支持以下两种安装方式:
(1)配置文件指定
1
2
3 |
[mysqld] plugin-
load
-
add
=mysql_clone.so clone=FORCE_PLUS_PERMANENT |
这里的clone,严格来说,不是参数名,而是插件名,可加可不加,FORCE_PLUS_PERMANENT 控制插件的行为。
有四个取值:
(2)动态加载
1
2
3 |
[mysqld] plugin-
load
-
add
=mysql_clone.so clone=FORCE_PLUS_PERMANENT |
查看插件是否安装成功
1
2
3
4 |
mysql> show plugins; ... | clone | ACTIVE | CLONE | mysql_clone.so | GPL | ... |
clone状态显示为”ACTIVE“代表插件加载成功。
Clone Plugin支持两种克隆方式:本地克隆和远程克隆。
本地克隆是在实例本地发起的,其语法如下:
1 |
CLONE
LOCAL
DATA DIRECTORY [=]
'clone_dir'
; |
其中,clone_dir是克隆目录。
下面看个具体的Demo。
创建克隆用户
1
2 |
mysql>
create
user
'clone_user'
@
'%'
identified
by
'clone_pass'
; mysql>
grant
backup_admin
on
*.*
to
'clone_user'
@
'%'
; |
创建克隆目录
1
2 |
# mkdir /data/mysql # chown -R mysql.mysql /data/mysql |
创建本地克隆
1
2 |
# mysql -uclone_user -pclone_pass mysql> clone
local
data directory=
'/data/mysql/3307'
; |
其中,“/data/mysql/3307” 是克隆目录,其需满足以下几点要求:
- 克隆目录必须是绝对路径。
- “/data/mysql”必须存在,且MySQL对其有可写权限。
- 3307不能存在。
查看克隆目录的内容
1
2
3
4
5
6
7
8
9
10
11
12
13 |
# ll /data/mysql/3307 total 172996 drwxr-x
--- 2 mysql mysql 89 May 24 22:37 #clone -rw-r
----- 1 mysql mysql 3646 May 24 22:37 ib_buffer_pool -rw-r
----- 1 mysql mysql 12582912 May 24 22:37 ibdata1 -rw-r
----- 1 mysql mysql 50331648 May 24 22:37 ib_logfile0 -rw-r
----- 1 mysql mysql 50331648 May 24 22:37 ib_logfile1 drwxr-x
--- 2 mysql mysql 6 May 24 22:37 mysql -rw-r
----- 1 mysql mysql 25165824 May 24 22:37 mysql.ibd drwxr-x
--- 2 mysql mysql 20 May 24 22:37 slowtech drwxr-x
--- 2 mysql mysql 28 May 24 22:37 sys -rw-r
----- 1 mysql mysql 10485760 May 24 22:37 undo_001 -rw-r
----- 1 mysql mysql 11534336 May 24 22:37 undo_002 |
相对于Xtrabackup,无需Prepare,直接即可启动使用。
1 |
# /usr/
local
/mysql/bin/mysqld
--no-defaults --datadir=/data/mysql/3307 --user mysql --port 3307 & |
远程克隆涉及两个实例,其中,待克隆的实例是Donor,接受克隆数据的实例是Recipient。克隆命令需在Recipient上发起,语法如下:
1
2
3
4 |
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权限,如上面创建的clone_user。
DATA DIRECTORY指定备份目录,不指定的话,则默认克隆到Recipient的数据目录下。
REQUIRE [NO] SSL,是否开启SSL通信。
下面,看个具体Demo。
首先,在Donor实例上创建克隆用户,加载Clone Plugin。
1
2
3 |
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'
; |
backup_admin是克隆操作必需权限。
接着,在Recipient实例上创建克隆用户,加载Clone Plugin。
1
2
3 |
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(阻塞DDL)和shutdown(重启实例)权限。
设置Donor白名单。Recipient只能克隆白名单中的实例。
1 |
mysql>
set
global
clone_valid_donor_list =
'192.168.244.10:3306'
; |
设置该参数需要SYSTEM_VARIABLES_ADMIN权限。
在Recipient上发起克隆命令
1
2
3 |
# mysql -urecipient_user -precipient_pass mysql> clone instance
from
'donor_user'
@
'192.168.244.10'
:3306 identified
by
'donor_pass'
; Query OK, 0
rows
affected (36.97 sec) |
远程克隆会依次进行以下操作:
(1) 获取备份锁。备份锁和DDL互斥。注意,不仅仅是Recipient,Donor上的备份锁同样会获取。
(2) DROP用户表空间。注意,DROP的只是用户数据,不是数据目录,也不包括mysql,ibdata等系统表空间。
(3)从Donor实例拷贝数据。对于用户表空间,会直接拷贝,如果是系统表空间 ,则会重命名为xxx.#clone,不会直接替代原文件。
1
2
3
4
5
6
7
8
9
10
11
12 |
ll /data/mysql/3306/data/ ... -rw-r
----- 1 mysql mysql 3646 May 25 07:20 ib_buffer_pool -rw-r
----- 1 mysql mysql 3646 May 27 07:31 ib_buffer_pool.#clone -rw-r
----- 1 mysql mysql 12582912 May 27 07:31 ibdata1 -rw-r
----- 1 mysql mysql 12582912 May 27 07:31 ibdata1.#clone -rw-r
----- 1 mysql mysql 50331648 May 27 07:32 ib_logfile0 -rw-r
----- 1 mysql mysql 50331648 May 27 07:31 ib_logfile0.#clone ... -rw-r
----- 1 mysql mysql 25165824 May 27 07:31 mysql.ibd -rw-r
----- 1 mysql mysql 25165824 May 27 07:31 mysql.ibd.#clone ... |
(4)重启实例。在启动的过程中,会用xxx.#clone替换掉原来的系统表空间文件。
查看克隆操作的进度主要依托于performance_schema.clone_status和performance_schema.clone_progress这两张表。
首先看看performance_schema.clone_status表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 |
mysql>
select
*
from
performance_schema.clone_status\G *************************** 1. row ***************************
ID: 1
PID: 0
STATE: Completed
BEGIN_TIME: 2020-05-27 07:31:24.220
END_TIME: 2020-05-27 07:33:08.185
SOURCE: 192.168.244.10:3306
DESTINATION:
LOCAL
INSTANCE
ERROR_NO: 0
ERROR_MESSAGE:
BINLOG_FILE: mysql-bin.000009 BINLOG_POSITION: 665197555
GTID_EXECUTED: 59cd4f8f-8fa1-11ea-a0fe-000c29f66609:1-560 1 row
in
set
(0.06 sec) |
顾名思义,该表记录了克隆操作的当前状态。
其中,
接下来看看performance_schema.clone_progress表。
1
2
3
4
5
6
7
8
9
10
11
12
13 |
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 | 2020-05-27 07:31:28.581661 | 2020-05-27 07:31:35.855706 | 1 | 0 | 0 | 0 | 0 | 0 | | 1 | FILE COPY | Completed | 2020-05-27 07:31:35.855952 | 2020-05-27 07:31:58.270881 | 2 | 482463294 | 482463294 | 482497011 | 0 | 0 | | 1 | PAGE COPY | Completed | 2020-05-27 07:31:58.271250 | 2020-05-27 07:31:58.719085 | 2 | 10977280 | 10977280 | 11014997 | 0 | 0 | | 1 | REDO COPY | Completed | 2020-05-27 07:31:58.720128 | 2020-05-27 07:31:58.930804 | 2 | 465408 | 465408 | 465903 | 0 | 0 | | 1 | FILE SYNC | Completed | 2020-05-27 07:31:58.931094 | 2020-05-27 07:32:01.063325 | 2 | 0 | 0 | 0 | 0 | 0 | | 1 | RESTART | Completed | 2020-05-27 07:32:01.063325 | 2020-05-27 07:32:59.844119 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | RECOVERY | Completed | 2020-05-27 07:32:59.844119 | 2020-05-27 07:33:08.185367 | 0 | 0 | 0 | 0 | 0 | 0 | +
------+-----------+-----------+----------------------------+----------------------------+---------+-----------+-----------+-----------+------------+---------------+ 7
rows
in
set
(0.00 sec) |
该表记录了克隆操作的进度信息。
注意,是当前值。
在前面,我们介绍过performance_schema.clone_status表,该表会记录Donor实例的一致性位置点信息。我们可以利用这些信息来搭建从库。
1
2
3
4
5
6
7 |
mysql>
select
*
from
performance_schema.clone_status\G *************************** 1. row *************************** ...
BINLOG_FILE: mysql-bin.000009 BINLOG_POSITION: 665197555
GTID_EXECUTED: 59cd4f8f-8fa1-11ea-a0fe-000c29f66609:1-560 1 row
in
set
(0.06 sec) |
这里,区分两种场景,GTID复制和基于位置点的复制。
1
2
3
4 |
mysql> CHANGE MASTER
TO
MASTER_HOST =
'master_host_name'
, MASTER_PORT = master_port_num,
...
MASTER_AUTO_POSITION = 1; mysql> START SLAVE; |
需要注意的是,无需额外执行set global gtid_purged操作。通过克隆数据启动的实例,gtid_purged已经初始化完毕。
1
2
3
4
5
6
7 |
mysql> show
global
variables
like
'gtid_purged'
; +
---------------+--------------------------------------------+ | Variable_name | Value | +
---------------+--------------------------------------------+ | gtid_purged | 59cd4f8f-8fa1-11ea-a0fe-000c29f66609:1-560 | +
---------------+--------------------------------------------+ 1 row
in
set
(0.00 sec) |
这里,同样要区分两种场景。
场景1,Recipient要作为Donor的从库。
1
2
3
4
5
6 |
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。
场景2,Donor本身就是一个从库,Recipient要作为Donor主库的从库。
1
2
3
4
5
6 |
mysql>
SELECT
MASTER_LOG_NAME, MASTER_LOG_POS
FROM
mysql.slave_relay_log_info; 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:mysql.slave_relay_log_info中的Master_log_name,Master_log_pos(分别对应 SHOW SLAVE STATUS 中的 Relay_Master_Log_File,Exec_Master_Log_Pos)。
在搭建从库时,建议设置--skip-slave-start。该参数默认为OFF,实例启动后,会自动执行START SLAVE操作。
如果Donor是个从库,Recipient会基于mysql.slave_master_info,mysql.slave_relay_log_info中的信息自动建立复制,很多时候,这未必是我们的预期行为。
克隆操作可细分为以下5个阶段。
1 |
[INIT]
---> [FILE COPY] ---> [PAGE COPY] ---> [REDO COPY] -> [Done] |
1、INIT:初始化一个克隆对象。
2、FILE COPY:拷贝所有数据文件。在拷贝之前,会记录一个LSN,作为“CLONE START LSN”,这个LSN其实是当前CHECKPOINT的LSN,同时启动“Page Tracking”特性。
“Page Tracking”会跟踪“CLONE START LSN”之后被修改的页,具体来说,会记录该页的Tablespace ID和page ID。数据文件拷贝结束后,会将当前CHECKPOINT的LSN记为“CLONE FILE END LSN”。
3、PAGE COPY:拷贝“CLONE START LSN”和“CLONE FILE END LSN”之间的页,在拷贝之前,会对这些页进行排序-基于Tablespace ID和page ID,尽量避免拷贝过程中出现随机读写。同时,开启“Redo Archiving”特性。
“Redo Archiving”会在后台开启一个归档线程将Redo文件中的内容按Chunk拷贝到归档文件中。通常来说,归档线程的拷贝速度会快于Redo日志的生成速度。即使慢于,在写入新的Redo日志时,也会等待归档线程完成拷贝,不会出现还未拷贝的Redo日志被覆盖的情况。当所有修改的页拷贝完毕后,会获取实例的一致性位置点信息,此时的LSN记为“CLONE LSN”。
4、REDO COPY:拷贝归档文件中“CLONE FILE END LSN”与“CLONE LSN”之间的Redo日志。
5、Done:调用snapshot_end()销毁克隆对象。
1、克隆期间,不允许执行DDL命令。同样,DDL会阻塞克隆命令的执行
2、Clone Plugin不会拷贝Donor的配置参数。
3、Clone Plugin不会拷贝Donor的二进制日志文件。
4、Clone Plugin只会拷贝InnoDB表的数据,对于其它存储引擎的表,只会拷贝表结构。
5、Donor实例中如果有表通过DATA DIRECTORY指定了绝对路径,在进行本地克隆时,会提示文件已存在。在进行远程克隆时,绝对路径必须存在且有可写权限。
6、不允许通过MySQL Router连接Donor实例。
7、执行CLONE INSTANCE操作时,指定的Donor端口不能为X Protocol端口。
除此之外,在进行远程克隆时,还会进行如下检查:
1、在实现上,两者都有FILE COPY和REDO COPY阶段,但Clone Plugin比XtraBackup多了一个PAGE COPY,由此带来的好处是,Clone Plugin的恢复速度比XtraBackup更快。
2、XtraBackup没有Redo Archiving特性,有可能出现未拷贝的Redo日志被覆盖的情况。
3、GTID下建立复制,无需额外执行set global gtid_purged操作。
需要注意的是,如果在执行DDL时,有CLONE命令在执行,DDL同样会因获取不到备份锁被阻塞,只不过,DDL操作的等待时长由lock_wait_timeout参数决定,该参数的默认值为31536000s,即365天。
InnoDB: Clone local replica:
InnoDB: Clone remote replica:
InnoDB: Clone Replication Coordinates
InnoDB: Clone Remote provisioning:
MySQL/InnoDB数据克隆插件(clone plugin)实现剖析
转转连接
http://blog.itpub.net/69912579/viewspace-2730737/
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31429259/viewspace-2731026/,如需转载,请注明出处,否则将追究法律责任。