1. 程式人生 > >技術分享 | 實戰 MySQL 8.0.17 Clone Plugin

技術分享 | 實戰 MySQL 8.0.17 Clone Plugin

原創: 陳俊聰

背景

很神奇,5.7.17 和 8.0.17,連續兩個17小版本都讓人眼前一亮。前者加入了組複製(Group Replication)功能,後者加入了克隆外掛(Clone Plugin)功能。今天我們實戰測試一下這個新功能。

 

克隆外掛簡介

克隆外掛允許在本地或從遠端 MySQL 例項克隆資料。克隆資料是儲存在 InnoDB 其中的資料的物理快照,其中包括庫、表、表空間和資料字典元資料。克隆的資料包含一個功能齊全的資料目錄,允許使用克隆外掛進行 MySQL 伺服器配置。

 

克隆外掛支援兩種克隆方式

  • 本地克隆

  • 遠端克隆

 

本地克隆

本地克隆操作將啟動克隆操作的 MySQL 伺服器例項中的資料克隆到同伺服器或同節點上的一個目錄裡

遠端克隆

預設情況下,遠端克隆操作會刪除接受者(recipient)資料目錄中的資料,並將其替換為捐贈者(donor)的克隆資料。(可選)您也可以將資料克隆到接受者的其他目錄,以避免刪除現有資料。

遠端克隆操作和本地克隆操作克隆的資料沒有區別,資料是相同的。

克隆外掛支援複製。除克隆資料外,克隆操作還從捐贈者中提取並傳輸複製位置資訊,並將其應用於接受者,從而可以使用克隆外掛來配置組複製或主從複製。使用克隆外掛進行配置比複製大量事務要快得多,效率更高。

 

實戰部分

一、本地克隆

安裝克隆外掛

啟動前

[mysqld]
plugin-load-add=mysql_clone.so

或執行中

INSTALL PLUGIN clone SONAME 'mysql_clone.so';

| 第二種方法會註冊到元資料,所以不用擔心重啟外掛會失效。兩種方法都很好用

檢查外掛有沒有啟用

mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE 'clone';
+-------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+-------------+---------------+
| clone | ACTIVE |
+-------------+---------------+
1 row in set (0.01 sec)

設定強制啟動失敗引數

[mysqld]
plugin-load-add=mysql_clone.so
clone=FORCE_PLUS_PERMANENT

 

如果克隆外掛對你們很重要,可以設定clone=FORCE_PLUS_PERMANENT或clone=FORCE。作用是:如果外掛未成功初始化,就會強制mysqld啟動失敗。

克隆需要的許可權

需要有備份鎖的許可權。備份鎖是 MySQL 8.0 的新特性之一,比5.7版本的flush table with read lock要輕量。

mysql> CREATE USER clone_user@'%' IDENTIFIED by 'password';
mysql> GRANT BACKUP_ADMIN ON *.* TO 'clone_user'; # BACKUP_ADMIN是MySQL8.0 才有的備份鎖的許可權

執行本地克隆

mysql -uclone_user -ppassword -S /tmp/mysql3008.sock
mysql> CLONE LOCAL DATA DIRECTORY = '/fander/clone_dir';

例子中需要 MySQL 的執行使用者擁有 fander 目錄的rwx許可權,要求 clone_dir 目錄不存在

本地克隆的步驟如下

  • DROP DATA

  • FILE COPY

  • PAGE COPY

  • REDO COPY

  • FILE SYNC

觀察方法如下

mysql> SELECT STAGE, STATE, END_TIME FROM performance_schema.clone_progress;
+-----------+-------------+----------------------------+
| STAGE | STATE | END_TIME |
+-----------+-------------+----------------------------+
| DROP DATA | Completed | 2019-07-25 21:00:18.858471 |
| FILE COPY | Completed | 2019-07-25 21:00:19.071174 |
| PAGE COPY | Completed | 2019-07-25 21:00:19.075325 |
| REDO COPY | Completed | 2019-07-25 21:00:19.076661 |
| FILE SYNC | Completed | 2019-07-25 21:00:19.168961 |
| RESTART | Not Started | NULL |
| RECOVERY | Not Started | NULL |
+-----------+-------------+----------------------------+
7 rows in set (0.00 sec)

當然還有另外一個觀察方法

mysql> set global log_error_verbosity=3;
Query OK, 0 rows affected (0.00 sec)

mysql> CLONE LOCAL DATA DIRECTORY = '/fander/clone6_dir';
Query OK, 0 rows affected (0.24 sec)

[root@192-168-199-101 data]# tailf mysql-error.err
2019-07-25T22:22:58.261861+08:00 8 [Note] [MY-013457] [InnoDB] Clone Begin Master Task by root@localhost
2019-07-25T22:22:58.262422+08:00 8 [Note] [MY-013457] [InnoDB] Clone Apply Master Loop Back
2019-07-25T22:22:58.262523+08:00 8 [Note] [MY-013457] [InnoDB] Clone Apply Begin Master Task
...
2019-07-25T22:22:58.471108+08:00 8 [Note] [MY-013458] [InnoDB] Clone Apply State FLUSH DATA:
2019-07-25T22:22:58.472178+08:00 8 [Note] [MY-013458] [InnoDB] Clone Apply State FLUSH REDO:
2019-07-25T22:22:58.506488+08:00 8 [Note] [MY-013458] [InnoDB] Clone Apply State DONE
2019-07-25T22:22:58.506676+08:00 8 [Note] [MY-013457] [InnoDB] Clone Apply End Master Task ID: 0 Passed, code: 0:
2019-07-25T22:22:58.506707+08:00 8 [Note] [MY-013457] [InnoDB] Clone End Master Task ID: 0 Passed, code: 0:

測試,起一個克隆的例項

/opt/mysql8.0/bin/mysqld --datadir=/fander/clone_dir --port=3333 --socket=/tmp/mysql3333.sock --user=mysql3008user --lower-case-table-names=1 --mysqlx=OFF

#解釋,因為我沒有使用my.cnf,所以加了比較多引數
#--datadir 指定啟動的資料目錄
#--port 指定啟動的MySQL監聽埠
#--socket 指定socket路徑
#--user `捐贈者`的目錄許可權是mysql3008user:mysql3008user,使用者也是mysql3008user,我沒有修改
#--lower-case-table-names=1 同`捐贈者`
#--mysqlx=OFF 不關閉的話,預設mysqlx埠會合`捐贈者`的33060重複衝突

#登入檢查
mysql -uroot -proot -S /tmp/mysql3333.sock
mysql> show master status\G # 可見GTID是`捐贈者`的子集,所以說明`接受者`直接和`捐贈者`建主從複製是很簡單的

 

二、遠端克隆

遠端克隆的前提條件和限制

  • 捐贈者和接受者都需要安裝克隆外掛

  • 捐贈者和接受者分別需要有至少BACKUP_ADMIN/CLONE_ADMIN許可權的賬號

    | 暗示了接受者必須先啟動一個數據庫例項(空或有資料的例項均可,因為都會被刪除)

  • 克隆目標目錄必須有寫入許可權

  • 克隆操作期間不允許使用 DDL,允許併發DML。要求相同版本號,您無法MySQL 5.7和MySQL 8.0之間進行克隆,而且要求版本>=8.0.17

  • 同一平臺同一架構,例如linux to windows、x64 to x32 是不支援。

  • 足夠的磁碟空間

  • 可以克隆操作一般表空間,但必須要有目錄許可權,不支援克隆使用絕對路徑建立的一般空間。與源表空間檔案具有相同路徑的克隆表空間檔案將導致衝突

  • 遠端克隆時不支援CLONE INSTANCE FROM中通過使用mysqlx的埠

  • 克隆外掛不支援克隆MySQL伺服器配置my.cnf等

  • 克隆外掛不支援克隆二進位制日誌。

  • 克隆外掛僅克隆儲存的資料 InnoDB。不克隆其他儲存引擎資料。MyISAM並且 CSV儲存在包括sys模式的任何模式中的表都被克隆為空表。

  • 不支援通過MySQL router連線到捐贈者例項。

  • 一些引數是必須一致的,例如innodb_page_size、innodb_data_file_path、--lower_case_table_    names

  • 如果克隆加密或頁面壓縮資料,則捐贈者和接收者必須具有相同的檔案系統塊大小

  • 如果要克隆加密資料,則需要安全連線

  • clone_valid_donor_list 在接受者的設定必須包含捐贈者 MySQL 伺服器例項的主機地址。

  • 必須沒有其他克隆操作正在執行。一次只允許一次克隆操作。要確定克隆操作是否正在執行,請查詢該 clone_status表。

  • 預設情況下,克隆資料後會自動重新啟動接受者 MySQL 例項。要自動重新啟動,必須在接收方上提供監視程序以檢測伺服器是否已關閉。否則,在克隆資料後,克隆操作將停止並出現以下錯誤,並且關閉接受者 MySQL 伺服器例項:

 

| 此錯誤不表示克隆失敗。這意味著必須在克隆資料後手動重新啟動接受者的 MySQL 例項。

遠端克隆實戰

假設前提條件都滿足,步驟如下

和本地克隆一樣,遠端克隆需要外掛安裝和使用者授權。捐贈者、接受者的授權略有不同。

1. 確保捐贈者和接受者都安裝了克隆外掛

INSTALL PLUGIN clone SONAME 'mysql_clone.so';

2. 使用者賬號授權

捐贈者授權

mysql> CREATE USER clone_user@'192.168.199.101' IDENTIFIED by 'password1';
mysql> GRANT BACKUP_ADMIN ON *.* TO 'clone_user'@'192.168.199.101'; # BACKUP_ADMIN是MySQL8.0 才有的備份鎖的許可權

接受者授權

mysql> CREATE USER clone_user@'192.168.199.102' IDENTIFIED by 'password2';
mysql> GRANT CLONE_ADMIN ON *.* TO 'clone_user'@'192.168.199.102';

 

| CLONE_ADMIN許可權 = BACKUP_ADMIN許可權 + SHUTDOWN許可權。SHUTDOWN僅限允許使用者shutdown和restart mysqld。授權不同是因為,接受者需要restart mysqld。

3. 接受者設定捐贈者列表清單

mysql -uclone_user -ppassword2 -h192.168.199.102 -P3008
mysql> SET GLOBAL clone_valid_donor_list = '192.168.199.101:3008';

 

這看起來是一個安全相關引數。多個例項用逗號分隔,例如“HOST1:PORT1,HOST2:PORT2,HOST3:PORT3”

接受者開始拉取克隆捐贈者資料​​​​​​​

CLONE INSTANCE FROM clone_user@'192.168.199.101':3008
IDENTIFIED BY 'password1';

遠端克隆步驟如下

mysql> SELECT STAGE, STATE, END_TIME FROM performance_schema.clone_progress;
+-----------+-----------+----------------------------+
| STAGE | STATE | END_TIME |
+-----------+-----------+----------------------------+
| DROP DATA | Completed | 2019-07-25 21:56:01.725783 |
| FILE COPY | Completed | 2019-07-25 21:56:02.228686 |
| PAGE COPY | Completed | 2019-07-25 21:56:02.331409 |
| REDO COPY | Completed | 2019-07-25 21:56:02.432468 |
| FILE SYNC | Completed | 2019-07-25 21:56:02.576936 |
| RESTART | Completed | 2019-07-25 21:56:06.564090 |
| RECOVERY | Completed | 2019-07-25 21:56:06.892049 |
+-----------+-----------+----------------------------+
7 rows in set (0.01 sec)

接受者如果非mysqld_safe啟動的,會報錯誤,但不影響克隆,需要您人手啟動mysqld即可。

ERROR 3707 (HY000): Restart server failed (mysqld is not managed by supervisor process).

實操後小結:克隆與xtrabackup的對比

  • 克隆和xtrabackup備份都屬於物理熱備,備份恢復原理也近似。

  • 克隆在恢復例項時需要先啟動一個例項並授權,而xtrabackup不需要。

  • xtrabackup在backup後需要apply log,克隆是類似mysqlbackup提供的backup-and-apply-log,合併在一起做。

  • xtrabackup備份檔案的許可權等於執行命令的人的許可權,恢復例項時需要人手chown回例項許可權,克隆備份後許可權和原資料許可權一致,無需再人手chown,方便恢復。

  • xtrabackup恢復時需要在mysql中執行reset master;然後set global gtid_purged="UUID:NUMBER",具體的UUID:NUMBER的值為備份檔案中的xtrabackup_info檔案的內容;克隆不需要這個操作步驟,預設克隆完就可以建立複製了。

  • xtrabackup備份完一般是scp拷貝到另外一臺機器恢復,走的是22埠;克隆走的是MySQL的監聽埠。所以在目錄許可權正確的情況下,甚至根本不需要登入Linux伺服器的許可權。如下:

[root@192-168-199-103 ~]# mysql -uroot -ppassword2 -h192.168.199.102 -P3008 -e "SET GLOBAL clone_valid_donor_list = '192.168.199.101:3008';"

mysql: [Warning] Using a password on the command line interface can be insecure.
[root@192-168-199-103 ~]# mysql -uroot -ppassword2 -h192.168.199.102 -P3008 -e "CLONE INSTANCE FROM root@'192.168.199.101':3008 IDENTIFIED BY 'password1';"
mysql: [Warning] Using a password on the command line interface can be insecure.

三、利用克隆建立主從複製

克隆出來的接受者例項,可以與捐贈者建立主從複製。當然建立組複製也是可以的,鑑於篇幅的原因,不做示例有興趣可以閱讀官方文件18.4.3.1節“克隆分散式恢復”。

| https://dev.mysql.com/doc/refman/8.0/en/group-replication-cloning.html

傳統複製時,通過以下命令檢視postion位置

mysql> SELECT BINLOG_FILE, BINLOG_POSITION FROM performance_schema.clone_status;
+------------------+-----------------+
| BINLOG_FILE | BINLOG_POSITION |
+------------------+-----------------+
| mysql-bin.000014 | 2179 |
+------------------+-----------------+
1 row in set (0.01 sec)

GTID複製時,通過以下命令檢視GTID位置​​​​​​​

mysql> SELECT @@GLOBAL.GTID_EXECUTED;
+-------------------------------------------+
| @@GLOBAL.GTID_EXECUTED |
+-------------------------------------------+
| 990fa9a4-7aca-11e9-89fa-000c29abbade:1-11 |
+-------------------------------------------+
1 row in set (0.00 sec)

假設已經有如下授權,我們就可以建立複製啦

create user repl@'%' identified WITH 'mysql_native_password' by 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'%';

建立GTID主從複製關係

(接受者上)

  1. CHANGE MASTER TO
    MASTER_HOST='192.168.199.101',
    MASTER_USER='repl',
    MASTER_PASSWORD='password',
    MASTER_PORT=3008,
    MASTER_AUTO_POSITION=1;
    
    

     

監控克隆操作

檢查克隆進度

mysql> SELECT STATE FROM performance_schema.clone_status;
+-----------+
| STATE |
+-----------+
| Completed |
+-----------+
1 row in set (0.00 sec)

 

SELECT STATE, ERROR_NO, ERROR_MESSAGE FROM performance_schema.clone_status;

檢查克隆是否出錯

mysql> SELECT STATE, ERROR_NO, ERROR_MESSAGE FROM performance_schema.clone_status;
+-----------+----------+---------------+
| STATE | ERROR_NO | ERROR_MESSAGE |
+-----------+----------+---------------+
| Completed | 0 | |
+-----------+----------+---------------+
1 row in set (0.00 sec)

檢查克隆次數

show global status like 'Com_clone'; # `捐贈者` 每次+1,`接受者` 0

隨時可以kill掉克隆

使用
SELECT * FROM performance_schema.clone_status\G
或
show processlist
檢視執行緒ID,然後kill ID

總結

克隆功能非常有趣。他操作簡單,可以用於快速搭建、恢復主從複製或組複製,可以部分取代開源熱備軟體xtrabackup,期待未來官方會把他做得越來越好,功