이 문서는 다음 link 를 번역한 내용과 + 테스트 중 확인한 내용을 추가하였다.
https://mysqlserverteam.com/clone-create-mysql-instance-replica/
Cloning MySQL instance
복제를 위해서 MySQL replica 를 만드는 것은 너무 많은 과정이 포함되어있어서 번거롭다.
(백업/복구/binlog file, position 맞추기 등 - 이 post 에서는 해당 내용을 설명하지는 않겠다.)
Clone plugin 을 사용하면 replica 생성을 간단하게 해결할 수 있다.
MySQL 8.0.17 부터 CLONE SQL 구문이 소개되었다.
현재 MySQL 서버에서 clone 하여 다른 MySQL 서버에 구성한다.
Doner : source server (백업 대상 서버)
Recipient : target server (replica)
InnoDB 스토리지 엔진에 저장된 data 와 meta data 모두를 일관성있게 snapshot 하여 target 으로 옮긴다.
Recipient 서버에서 CLONE SQL 구문 실행 시 서버는 자동으로 재시작 된다. (운영 중인 slave 에서 명령을 실행하면 안된다)
restart 는 과거 방식으로 데이터가 복사되어 전달하는 것과 같이 clone 된 snapshot 데이터의 recovery 를 포함된다.
recovery 단계가 완료되면 Donor 의 clone 인 Recipient (replica) 는 사용할 준비가 된다.
cloning process 에 대해 몇 가지 중요한 부분은 다음과 같다.
-
MySQL 설정 parameter 는 clone 되지 않으며 Recipient 는 clone 되기 전의 configuration 파라미터를 유지한다.
그러나 Donor 와 Recipient 사이에 일치해야 하는 스토리지 configuration 에 대해서는 CLONE 이 parameter 가 일치하지 않는다는 error 를 발생시킨다. ( innodb_page_size 와 같은 )
-
Clone 플러그인은 binary log 는 clone 하지 않는다. HA 클러스터에 노드 추가를 위해서 donor 의 binary log 복제는 필요하지 않음.
-
Clone 플러그인은 InnoDB storage engine 만 지원한다. MyISAM 과 CSV 는 비어있는 테이블로 생성된다.
-
Clone 은 Donor 에서 수행되는 모든 동시 DDL 을 block 한다.
-
Recipient 는 donner 의 instance 가 복제 시작되는 시점에 binary log 를 포함한 모든 데이터를 삭제한다.
( 이미 운영중인 서버에서 실행하면 데이터가 모두 삭제되니 주의해야 한다 !! ) -
CLONE 하기 전에 반드시 recipient 의 데이터 백업이 필요하다.
Step-1 : Donor 선택 및 설정
mysql> INSTALL PLUGIN CLONE SONAME "mysql_clone.so"; Query OK, 0 rows affected (0.60 sec)
mysql> CREATE USER clone_user IDENTIFIED BY "clone_password"; Query OK, 0 rows affected (0.02 sec)
mysql> GRANT BACKUP_ADMIN ON *.* TO clone_user ; Query OK, 0 rows affected (0.02 sec)
-- 진행 과정을 확인하기 위해 performance_schema 와 execute 권한을 수행
mysql> GRANT SELECT ON performance_schema.* TO clone_user ; Query OK, 0 rows affected (0.00 sec)
mysql> GRANT EXECUTE ON *.* to clone_user ; Query OK, 0 rows affected (0.00 sec) |
Step-2 : Recipient 선택 및 설정
Donor 의 clone 이 되기 위한 서버를 선택한다.
clone plugin 을 설치하고, 현재 인스턴스 데이터를 clone 된 data 로 교체할 user 에게 CLONE_ADMIN 권한을 부여한다.
valid donor 들의 리스트를 설정한다.
mysql> INSTALL PLUGIN CLONE SONAME "mysql_clone.so"; Query OK, 0 rows affected (0.37 sec)
mysql> SET GLOBAL clone_valid_donor_list = "donor.host.com:3306"; Query OK, 0 rows affected (0.00 sec)
mysql> CREATE USER clone_user IDENTIFIED BY "clone_password" ; Query OK, 0 rows affected (0.04 sec)
mysql> GRANT CLONE_ADMIN ON *.* to clone_user ; Query OK, 0 rows affected (0.01 sec)
-- 마찬가지로 상황을 확인하기 위한 권한을 부여한다.
mysql> GRANT SELECT ON performance_schema.* TO clone_user ; Query OK, 0 rows affected (0.01 sec)
mysql> GRANT EXECUTE ON *.* to clone_user ; Query OK, 0 rows affected (0.01 sec)
|
Step-3. Recipient 에 접속하고 CLONE SQL 구문을 실행
data cloning 이 진행 되는 동안에 Recipient 의 performance_schema view 를 사용하여 clone 작업의 진행도를 확인할 수 있다.
mysql> CLONE INSTANCE FROM clone_user@donor.host.com:3306 IDENTIFIED BY "clone_password" ;
Query OK, 0 rows affected (22.67 sec)
|
위 명령이 완료되는 동안 mysql error log 에는 다음과 같이 남게된다.
2019-11-25T06:59:38.741186Z 79 [Warning] [MY-013460] [InnoDB] Clone removing all user data for provisioning: Started ... |
내부적으로 file 을 복사할 때, "#clone" 이라는 postfix 를 붙이고 copy 된다.
drwxr-x--- 2 mysql mysql 4096 Nov 25 06:51 sys |
CLONE 명령을 수행하는 중에 Donor 와 Recipient 에 어떤 쿼리가 수행되는지 확인했다.
의외로 Donor 에 특별한 명령이 수행되지 않았음. ( 로그에 안남을 수도 있겠지만 .. )
Recipient |
2019-11-25T08:01:04.663511Z 67 Query CLONE INSTANCE FROM 'clone_user'@'donor.host.com':3306 IDENTIFIED BY <secret> 2019-11-25T08:01:04.782376Z 67 Execute SET SQL_LOG_BIN = OFF 2019-11-25T08:01:04.782565Z 67 Execute SET FOREIGN_KEY_CHECKS=0 2019-11-25T08:01:04.809630Z 67 Execute DROP TABLE `hong`.`item` 2019-11-25T08:01:04.819693Z 67 Execute DROP TABLE `hong`.`country` 2019-11-25T08:01:04.829376Z 67 Execute DROP TABLE `hong`.`sales` 2019-11-25T08:01:04.840812Z 67 Execute SET SQL_LOG_BIN = OFF 2019-11-25T08:01:04.840943Z 67 Execute SET FOREIGN_KEY_CHECKS=0 2019-11-25T08:01:04.841032Z 67 Execute DROP SCHEMA `mysqlslap` 2019-11-25T08:01:04.843783Z 67 Execute DROP SCHEMA `hong` 2019-11-25T08:01:04.846438Z 67 Execute DROP SCHEMA `ds0` 2019-11-25T08:01:04.849159Z 67 Execute DROP SCHEMA `ds1` 2019-11-25T08:01:04.852039Z 67 Execute SET SQL_LOG_BIN = OFF 2019-11-25T08:01:04.852159Z 67 Execute SET FOREIGN_KEY_CHECKS=0 2019-11-25T08:01:04.852247Z 67 Execute STOP SLAVE 2019-11-25T08:01:04.852329Z 67 Execute RESET MASTER 2019-11-25T08:01:22.578730Z 67 Query SELECT DATABASE() |
Donor |
2019-11-25T08:01:04.680779Z 941 Connect clone_user@recipient.server.com on using SSL/TLS 2019-11-25T08:01:04.690251Z 942 Connect clone_user@recipient.server.com on using SSL/TLS 2019-11-25T08:01:10.145412Z 944 Connect clone_user@recipient.server.com on using SSL/TLS |
mysql> select STATE, CAST(BEGIN_TIME AS DATETIME) as "START TIME", CASE WHEN END_TIME IS NULL THEN LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ') ELSE LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ') END as DURATION from performance_schema.clone_status;
+-----------+---------------------+------------+ | STATE | START TIME | DURATION | +-----------+---------------------+------------+ | Completed | 2019-11-25 07:08:23 | 32.45 s | +-----------+---------------------+------------+ 1 row in set (0.14 sec) |
DURATION 컬럼 값으로 얼마나 소요 되었는지 확인할 수 있다. m 은 minute 이다.
select STAGE, STATE, CAST(BEGIN_TIME AS TIME) as "START TIME", CASE WHEN END_TIME IS NULL THEN LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(now()) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ') ELSE LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ') END as DURATION, LPAD(CONCAT(FORMAT(ROUND(ESTIMATE/1024/1024,0), 0), " MB"), 16, ' ') as "Estimate", CASE WHEN BEGIN_TIME IS NULL THEN LPAD('0%', 7, ' ') WHEN ESTIMATE > 0 THEN LPAD(CONCAT(CAST(ROUND(DATA*100/ESTIMATE, 0) AS BINARY), "%"), 7, ' ') WHEN END_TIME IS NULL THEN LPAD('0%', 7, ' ') ELSE LPAD('100%', 7, ' ') END as "Done(%)" from performance_schema.clone_progress;
+-----------+-----------+------------+------------+------------------+---------+ | STAGE | STATE | START TIME | DURATION | Estimate | Done(%) | +-----------+-----------+------------+------------+------------------+---------+ | DROP DATA | Completed | 07:08:23 | 2.08 s | 0 MB | 100% | | FILE COPY | Completed | 07:08:25 | 8.62 s | 184 MB | 100% | | PAGE COPY | Completed | 07:08:33 | 304.76 ms | 0 MB | 100% | | REDO COPY | Completed | 07:08:34 | 300.91 ms | 0 MB | 100% | | FILE SYNC | Completed | 07:08:34 | 11.36 s | 0 MB | 100% | | RESTART | Completed | 07:08:45 | 4.86 s | 0 MB | 100% | | RECOVERY | Completed | 07:08:50 | 4.91 s | 0 MB | 100% | +-----------+-----------+------------+------------+------------------+---------+ 7 rows in set (0.00 sec) |
Clone 은 FILE COPY 단계 안에 있다.
대부분의 Clone 단계가 완료되면 clone 은 FILE SYNC 단계가 된다. ( disk 로 data sync )
FILE SYNC 단계 이후에 clone 명령은 완료되고 server 로 부터 자동 재시작 될 것을 return 한다.
RESTART, RECOVERY 단계에서는 서버를 사용할 수 없다.
이는 clone 된 데이터로부터 전체 recovery 를 수행하기 때문이다.
redo logs 들이 적용되고 새로운 clone 이 snapshot GTID 로 sync 되면
binlog 를 사용하여 upstream 서버를 따라잡을 수 있다.
이러한 과정이 종료되어야 상태를 확인할 수 있다.
Step-4. clone 이 성공적으로 완료되었는지 검증
CLONE SQL 은 완료 이후 서버 재시작이 필요하다.
CLONE SQL 이 성공적으로 return 되면 서버가 자동으로 shutdown 된다.
CLONE SQL 을 실행하는 client 는 connection 이 끊어진다.
: 만일 auto-reconnection 이 활성화 되어있다면 커넥션은 서버 재시작 이후에 재접속된다. 아니라면 수동으로 재접속 해야한다.
Recipient 는 서버 shutdown, restart 를 모니터링 과정에서 감지하는 환경에서 수행되어야 한다.
모니터링 과정이 없을 경우 다음과 같은 에러가 발생할 수 있다.
ERROR 3707 (HY000): Restart server failed (mysqld is not managed by supervisor process).
위 에러는 clone 실패를 의미하는 것이 아니라, 수동으로 restart 가 필요하고 client 가 server 로 재접속 해야 한다는 것을 의미한다.
클라이언트가 재접속하면 clone 이 성공적으로 완료되었는지 확인한다.
select STATE, ERROR_NO, BINLOG_FILE, BINLOG_POSITION, GTID_EXECUTED, CAST(BEGIN_TIME AS DATETIME) as "START TIME", CAST(END_TIME AS DATETIME) as "FINISH TIME", sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))) as DURATION from performance_schema.clone_status \G
*************************** 1. row *************************** STATE: Completed ERROR_NO: 0 BINLOG_FILE: mysql-bin.000006 BINLOG_POSITION: 1207 GTID_EXECUTED: 245fe0b5-f088-11e9-a300-46de8e9f7ae5:1-288235 START TIME: 2019-11-25 07:08:23 FINISH TIME: 2019-11-25 07:08:55 DURATION: 32.45 s -- 소요시간 1 row in set (0.00 sec)
|
Clone 이 성공적으로 완료되되었음을 확인하였다. 다음 쿼리로 모든 단계가 성공적으로 완료되었음을 확인한다.
select STAGE, STATE, CAST(BEGIN_TIME AS DATETIME) as "START TIME", CAST(END_TIME AS DATETIME) as "FINISH TIME", LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ') as DURATION from performance_schema.clone_progress; select STAGE, STATE, CAST(BEGIN_TIME AS TIME) as "START TIME", CAST(END_TIME AS TIME) as "FINISH TIME", LPAD(sys.format_time(POWER(10,12) * (UNIX_TIMESTAMP(END_TIME) - UNIX_TIMESTAMP(BEGIN_TIME))), 10, ' ') as DURATION from performance_schema.clone_progress;
+-----------+-----------+------------+-------------+------------+ | STAGE | STATE | START TIME | FINISH TIME | DURATION | +-----------+-----------+------------+-------------+------------+ | DROP DATA | Completed | 07:08:23 | 07:08:25 | 2.08 s | | FILE COPY | Completed | 07:08:25 | 07:08:33 | 8.62 s | | PAGE COPY | Completed | 07:08:33 | 07:08:34 | 304.76 ms | | REDO COPY | Completed | 07:08:34 | 07:08:34 | 300.91 ms | | FILE SYNC | Completed | 07:08:34 | 07:08:45 | 11.36 s | | RESTART | Completed | 07:08:45 | 07:08:50 | 4.86 s | | RECOVERY | Completed | 07:08:50 | 07:08:55 | 4.91 s | +-----------+-----------+------------+-------------+------------+ |
Recipient 는 정확한 GTID 값으로 Donor 의 clone 이 되었다.
이로써 GTID 또는 binary log position 을 기반으로 HA 클러스터에 조인할 준비가 되었다.
MySQL HA 문서에서 slave 로 MySQL instance 설정 또는 group replication node 설정에 대한 더 많은 정보를 확인하기 바란다.