MySQL GTID 시작하기
2017.01.14 MySQL PG 세미나
전세웅 (SK Telecom)
『돌고래사육사』 http://seuis398.blog.me
MySQL GTID 시작하기
MySQL GTID 개요
1 / 15
mysql-bin.102
mysql-bin.1019d850d65-219f-11e6-b752-08002702c825:1-30
9d850d65-219f-11e6-b752-08002702c825:31-81
DB1 (MASTER)
DB2 (SLAVE) DB3 (SLAVE)
mysql-bin.207
mysql-bin.206
Replication
9d850d65-219f-11e6-b752-08002702c825:1-50
9d850d65-219f-11e6-b752-08002702c825:51-81
Replication
현재 복제 포지션
DB1 mysql-bin.102 , 20352
= 9d850d65-219f-11e6-b752-08002702c825:81
DB2의 복제 포지션으로 전환
9d850d65-219f-11e6-b752-08002702c825:81
= DB2 mysql-bin.207 , 2974
서로 다른 노드의 Binary Log / Position을
mapping 시킬 수 있는 기반 정보를 제공
File Offset = 20352
File Offset = 2974
GTID를 이해하기 위한 기본 개념(I)
GTID
• Server UUID + Transaction 순차번호로 구성 (예: 9d850d65-219f-11e6-b752-08002702c825:33)
• Server UUID 값은 SHOW VARIABLES LIKE ‘server_uuid‘로 확인 가능
GTID SET
• GTID의 집합 (예: 9d850d65-219f-11e6-b752-08002702c825:1-33:38-42)
EXECUTED GTID ★
• 초기화 이후 실행된 GTID SET을 의미하며, gtid_executed 시스템 변수에서 확인 가능
• Binary Log를 남기는 Master 입장에서는 자신의 GTID 발급 현황을,
Slave 입장에서는 Master의 트랜잭션이 어디까지 반영되었는지를 의미하기도 함
PURGED GTID
• 실행 후 Binary Log Purge까지 완료된 GTID SET을 의미하며, gtid_purged 시스템 변수에서 확인 가능
• Slave가 gtid_purged 범위의 GTID를 요청하면 해당 요청은 처리 불가
※ gtid_executed, gtid_purged 시스템 변수 값은 DB 재기동 시점에 계산되어 초기화
MySQL GTID 시작하기 2 / 15
GTID를 이해하기 위한 기본 개념(I)
mysql-bin.002
mysql-bin.003
mysql-bin.004
mysql-bin.001
Binary Log Purge
9d850d65-219f-11e6-b752-08002702c825:1-30
9d850d65-219f-11e6-b752-08002702c825:31-81
9d850d65-219f-11e6-b752-08002702c825:82-102
9d850d65-219f-11e6-b752-08002702c825:103-114
Purged Gtid
9d850d65-219f-11e6-b752-08002702c825:1-81
Executed Gtid
9d850d65-219f-11e6-b752-08002702c825:1-114
Slave 전파
복제되어 처리되는 트랜잭션에 의해 Slave DB에서도 동일한
Executed GTID 값을 가지게 됨
MySQL GTID 시작하기 3 / 15
주제1. IO Thread와 SQL Thread에게 GTID란?
(1) IO Thread에게 GTID란?
• IO Thread가 초기화(change master) 될 때 Master에서 어떤 Log를 받아와야 될지 판단하는 기준
• “Master의 Executed GTID – 자신의 Executed GTID 영역”을 받아와서 Relay Log에 저장
• Master의 Executed GTID : 9d850d65-219f-11e6-b752-08002702c825:1-102
• 자신의 Executed GTID : 9d850d65-219f-11e6-b752-08002702c825:1-90:96-100
• Relay Log로 가져오게 되는 트랜잭션은 9d850d65-219f-11e6-b752-08002702c825:91-95:101-102
• IO Thread 초기화 이후에는 non-GTID 모드와 동일하게 Binary Log File / Position 기반으로 동작
(2) SQL Thread에게 GTID란?
• SQL Thread는 non-GTID 모드와 동일하게 Relay Log에 저장된 트랜잭션을 순차 처리함
• 다만, GTID 모드에서는 SQL Thread가 실행하는 GTID 트랜잭션의 기록만 추가로 남김 (gtid_executed)
※ GTID는 IO Thread가 초기화 될 때 Master의 Binary Log File/Position을 찾기 위해 사용됨
그리고 필요할 때 쓰기 위해 SQL Thread가 동작할 때 실행된 GTID에 대한 기록을 남김
이외의 기본적인 Replication 동작은 GTID나 non-GTID나 동일함
MySQL GTID 시작하기 4 / 15
주제2. log-bin / log-slave-updates 옵션의 사용
(1) 5.6 버전과 5.7 버전의 요구사항이 다르다.
• 5.6 버전까지 GTID를 사용하기 위해서는 복제 그룹의 모든 DB가 log-bin / log-slave-updates 옵션을 사용해야 함
• 누구나 Master가 될 수 있다는 기본적인 GTID 컨셉을 충족하기 위함
• 복제된 트랜잭션이 어디까지 수행되었는지 기록을 해야 하기 때문
• DB 재기동 시점에 Local에 저장된 첫번째, 마지막 Binary Log를 읽어 gtid_purged, gtid_executed 값을 계산
• 5.7 버전부터는 log-bin / log-slave-updates 옵션의 사용은 필수가 아님
• log-bin / log-slave-updates 옵션을 사용하지 않으면 mysql.gtid_executed 테이블에 필요한 정보를 저장
• 단, Master 역할을 부여받을 가능성이 있는 DB는 반드시 log-bin / log-slave-updates 옵션을 켜 두어야 함
MySQL GTID 시작하기 5 / 15
주제2. log-bin / log-slave-updates 옵션의 사용
(2) log-bin / log-slave-updates 옵션 사용시 유의할 점은?
• MySQL 데몬이 재기동 되는 경우 gtid_executed 값은 아래의 정보를 참조하여 초기화 됨
• mysql.gtid_executed 테이블에 저장된 GTID 값 ”binary log switch 시점에 1회 업데이트”
• Local에 남겨진 마지막 binary log의 GTID 값
• Binary Log 저장 안정성(sync_binlog) 확보 실패 혹은 임의 삭제 시 gtid_executed 변수의 잘못된 초기화를 유발
<사례> Slave MySQL 데몬 crash 후 binary log를 유실한 상황
mysql-bin.003
mysql-bin.004
9d850d65-219f-11e6-b752-08002702c825:82-102
9d850d65-219f-11e6-b752-08002702c825:103-114
mysql.gtid_executed 테이블
9d850d65-219f-11e6-b752-08002702c825:1-102
9d850d65-219f-11e6-b752-08002702c825:113-114
트랜잭션의 Binary Log flush 실패(유실)
slave> show global variables like 'gtid_executed';
+---------------+----------------------------------------------------+
| Variable_name | Value |
+---------------+----------------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-112:115-240 |
+---------------+----------------------------------------------------+
master> show global variables like 'gtid_executed';
+---------------+--------------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-240 |
+---------------+--------------------------------------------+
???
MySQL GTID 시작하기 6 / 15
주제2. log-bin / log-slave-updates 옵션의 사용
7 / 15
(2) log-bin / log-slave-updates 옵션 사용시 유의할 점은?
• Slave DB의 gtid_executed 값에 빈 구간(113-114)이 발생
• 하지만 복제는 여전히 잘 되고, 데이터 정합성에도 전혀 문제가 없음
• 당장 문제가 없는 것은 GTID 복제 역시 Log File / Position 기반으로 동작하기 때문 ”mysql.slave_relay_log_info”
• IO Thread가 초기화 되는 시점에 “Master의 Executed GTID – Slave의 Executed GTID 영역”을 받아와서 Relay Log
에 저장하게 되며 문제는 여기서 발생하게 됨
Case 1) GTID 113-114 트랜잭션이 이미 Master에서 Purge 되고 남아있지 않은 경우  복제 연결 불가
Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO
MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.‘
Case 2) GTID 113-114 트랜잭션이 Master에 남아있는 경우  중복 실행 (데이터 정합성 문제 혹은 복제 에러 발생)
slave> show global variables like 'gtid_executed';
+---------------+----------------------------------------------------+
| Variable_name | Value |
+---------------+----------------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-112:115-240 |
+---------------+----------------------------------------------------+
master> show global variables like 'gtid_executed';
+---------------+--------------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-240 |
+---------------+--------------------------------------------+
???
MySQL GTID 시작하기
???
주제2. log-bin / log-slave-updates 옵션의 사용
8 / 15
(2) log-bin / log-slave-updates 옵션 사용시 유의할 점은?
• 문제가 생기기 전에 보정 필요
• 방안1) 누락된 트랜잭션을 Empty 트랜잭션으로 Skip 처리
• 방안2) Slave의 gtid_executed 값을 적절히 변경
slave> show global variables like 'gtid_executed';
+---------------+----------------------------------------------------+
| Variable_name | Value |
+---------------+----------------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-112,115-240 |
+---------------+----------------------------------------------------+
???
slave> STOP SLAVE SQL_THREAD;
slave> SET GTID_NEXT='9d850d65-219f-11e6-b752-08002702c825:113';
slave> BEGIN; COMMIT;
slave> SET GTID_NEXT='AUTOMATIC';
slave> START SLAVE SQL_THREAD;
slave> STOP SLAVE SQL_THREAD;
slave> show global variables like ‘gtid_executed’;
… '9d850d65-219f-11e6-b752-08002702c825:285’ …
slave> RESET MASTER;
slave> SET GLOBAL GTID_PURGED='9d850d65-219f-11e6-b752-08002702c825:1-285';
slave> START SLAVE SQL_THREAD ;
MySQL GTID 시작하기
주제2. log-bin / log-slave-updates 옵션의 사용
9 / 15
(3) log-bin / log-slave-updates 옵션을 사용하지 않은 경우 유의할 점은?
• 트랜잭션 당 1건의 Record가 mysql.gtid_executed 테이블에 Insert
• N 건(기본 1000)의 Record가 쌓이면 N건을 Delete 하고 1건의 Record를 Insert (gtid_executed table compression)
• mysql.gtid_executed 테이블은 InnoDB 테이블이므로, ACID transaction 처리가 가능하므로 유실은 발생하지 않음
• MySQL 데몬이 재기동 되는 경우 gtid_executed 값은 mysql.gtid_executed 테이블의 값을 참조하여 초기화 됨
9d850d65-219f-11e6-b752-08002702c825 1000 1000
9d850d65-219f-11e6-b752-08002702c825 1001 1001
…
9d850d65-219f-11e6-b752-08002702c825 2000 2000 복제된 트랜잭션 1건당 1 Record 생성
9d850d65-219f-11e6-b752-08002702c825 1 1000
9d850d65-219f-11e6-b752-08002702c825 1001 1001
…
9d850d65-219f-11e6-b752-08002702c825 2000 2000
9d850d65-219f-11e6-b752-08002702c825 1 2000 압축된 결과 저장
삭제
MySQL GTID 시작하기
주제2. log-bin / log-slave-updates 옵션의 사용
10 / 15
(3) log-bin / log-slave-updates 옵션을 사용하지 않은 경우 유의할 점은?
• 여기서 잠깐!!! InnoDB에 대량의 Insert, Delete 작업이 복제 트랜잭션 건수만큼 추가
• InnoDB 테이블의 기본적인 IO 메커니즘을 따르므로, 대량의 insert / delete에 따른 부하가 추가됨
• Master의 변경량이 많아진다면?
※ mysql.gtid_executed 테이블의 압축에 대한 로직은 MySQL Reference Manual에 잘못 설명이 되어 있음
Manual : log-bin 설정에 따라 다른 동작  실제 : log-bin / log-slave-updates 설정 따라 다른 동작
gtid_executed
INSERT 1 Row
redo undo
Compression
DELETE N Rows
INSERT 1 Row
Purge
Old Trx
---TRANSACTION 14349675830, ACTIVE 4787 sec fetching rows
mysql tables in use 1, locked 1
1766093 lock struct(s), heap size 189702352, 23552816 row
lock(s), undo log entries 23552812
MySQL thread id 2, OS thread handle 140153037256448, query
id 0 Compressing gtid_executed table
------------
TRANSACTIONS
------------
Trx id counter 19540270802
Purge done for trx's n:o < 17490950910 undo n:o < 0 state:
History list length 1024727771
MySQL GTID 시작하기
주제3. 백업 데이터로 복구
11 / 15
Nothing Special !!
• IO Thread가 적절하게 Binary Log를 가져올 수 있도록 gtid_executed 값을 설정해 주면 됨
• mysqldump, xtrabackup 등의 도구에서 남겨준 gtid_executed 값을 참조하거나, 운영자가 직접 확인
• 신규 서버에 데이터 복구가 완료된 후
• GTID_EXECUTED 시스템 변수는 READ ONLY !!!
RESET MASTER로 GTID 초기화 후 GTID_PURGED 값을 설정 (GTID_EXECUTED 값은 자동으로 설정)
• 만약 Multi Source Replication을 사용하는 Slave라서 Master DB가 여러 대라면?
mysql> SET GLOBAL GTID_EXECUTED='9d850d65-219f-11e6-b752-08002702c825:1-2000';
ERROR 1238 (HY000): Variable 'gtid_executed' is a read only variable
???
mysql> RESET MASTER;
mysql> SET GLOBAL GTID_PURGED='9d850d65-219f-11e6-b752-08002702c825:1-2000';
mysql> RESET MASTER;
mysql> SET GLOBAL GTID_PURGED='9d850d65-219f-11e6-b752-08002702c825:1-2000,
a17a1326-219f-11e6-88f7-080027ee5436:1-520’;
MySQL GTID 시작하기
주제4. Reset Master의 역습
12 / 15
• Non-GTID 복제에서 Slave DB에서 수행하는 Reset Master는 복제에 아무런 영향을 주지 않음
• Reset Master 커맨드는 gtid_executed 시스템 변수를 초기화 시키기 때문에, GTID 복제에서 문제를 일으킴
• IO Thread가 초기화 될 때 문제가 발생하므로, 앞서 다뤘던 방법을 참고하여 보정 작업 필요
slave> reset master;
…
slave> show global variables like 'gtid_executed';
+---------------+----------------------------------------------+
| Variable_name | Value |
+---------------+----------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:225-240 |
+---------------+----------------------------------------------+
master> show global variables like 'gtid_executed';
+---------------+--------------------------------------------+
| Variable_name | Value |
+---------------+--------------------------------------------+
| gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-240 |
+---------------+--------------------------------------------+
???
MySQL GTID 시작하기
GTID를 이해하기 위한 기본 개념(II)
13 / 15
GTID_MODE
• GTID 발급 여부와 GTID를 부여받지 않은 트랜잭션(Anonymous Transaction)의 허용 여부를 결정
• 5.6 버전 기준으로 ON / OFF 2가지 모드가 존재
• 5.7 버전 기준으로 OFF ↔ OFF_PERMISSIVE ↔ ON_PERMISSIVE ↔ ON 4가지 모드가 존재, 단계별 변경만 가능
<GTID MODE 호환표>
Master
Slave
OFF OFF_PERMISSIVE ON_PERMISSIVE ON
OFF Y Y N N
OFF_PERMISSIVE Y Y Y Y
ON_PERMISSIVE Y Y Y Y
ON N N Y Y
MySQL GTID 시작하기
ON
OFF
(empty)
PERMISSIVE
Master 입장에서의 동작
ON : GTID 부여
OFF : GTID 부여하지 않음
Slave 입장에서의 동작
PERMISSIVE : GTID/Anonymous 혼재 허용
주제5. GTID MODE 온라인 변경
14 / 15
5.7 버전에서 지원
https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-enable-gtids.html
1. 복제 그룹 내 모든 서버의 ENFORCE_GTID_CONSISTENCY 값을 ON 으로 변경한다.
GTID 환경에서 지원되지 않는 SQL을 사전에 검출하기 위함
원칙적으로는 해당 변수 값을 WARN으로 먼저 변경하여 문제가 발생하는 경우 Warning을 발생시키도록 함
장기간 모니터링 후 문제가 없다는 것을 확인하고, ON으로 변경해야 함
2. 복제 그룹 내 모든 서버의 GTID_MODE 값을 OFF_PERMISSIVE로 변경한다.
GTID가 부여된 트랜잭션이 넘어와도 처리할 수 있도록 하기 위함
3. 복제 그룹 내 모든 서버의 GTID_MODE 값을 ON_PERMISSIVE로 변경한다.
Master DB는 GTID가 부여하기 시작하고, Slave DB는 GTID 발급 여부와 관계없이 트랜잭션을 처리한다.
4. 잔여 Anonymous 트랜잭션 확인
모든 DB 노드에서 SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT‘ 결과 값을 확인
결과 값이 0인 상태가 한번이라도 보이면 OK
5. 복제 그룹 내 모든 서버의 GTID_MODE 값을 ON으로 변경한다.
더 이상 GTID가 발급되지 않은 트랜잭션은 존재하지 않음
6. Binary Log File / Position 기반으로 동작하던 복제를 Auto Position 모드로 변경한다.
STOP SLAVE; CHANGE MASTER TO MASTER_AUTO_POSITION=1; START SLAVE;
MySQL GTID 시작하기
주제5. GTID MODE의 혼용
15 / 15
5.7 버전에서만 가능
MySQL GTID 시작하기
Group 1 (GTID)
분석/통계 작업용 DB (DW) - Multi Source Replication 구성
GTID_MODE = OFF_PERMISSIVE
Slave가 OFF_PERMISSIVE인 경우 GTID_MODE=ON/OFF인 DB를 모두
Master로 인식할 수 있다.
Group 2 (GTID)
channel 1 channel 2
Group 3 (non-GTID)
channel 3
감사합니다.

MySQL GTID 시작하기

  • 1.
    MySQL GTID 시작하기 2017.01.14MySQL PG 세미나 전세웅 (SK Telecom) 『돌고래사육사』 http://seuis398.blog.me
  • 2.
    MySQL GTID 시작하기 MySQLGTID 개요 1 / 15 mysql-bin.102 mysql-bin.1019d850d65-219f-11e6-b752-08002702c825:1-30 9d850d65-219f-11e6-b752-08002702c825:31-81 DB1 (MASTER) DB2 (SLAVE) DB3 (SLAVE) mysql-bin.207 mysql-bin.206 Replication 9d850d65-219f-11e6-b752-08002702c825:1-50 9d850d65-219f-11e6-b752-08002702c825:51-81 Replication 현재 복제 포지션 DB1 mysql-bin.102 , 20352 = 9d850d65-219f-11e6-b752-08002702c825:81 DB2의 복제 포지션으로 전환 9d850d65-219f-11e6-b752-08002702c825:81 = DB2 mysql-bin.207 , 2974 서로 다른 노드의 Binary Log / Position을 mapping 시킬 수 있는 기반 정보를 제공 File Offset = 20352 File Offset = 2974
  • 3.
    GTID를 이해하기 위한기본 개념(I) GTID • Server UUID + Transaction 순차번호로 구성 (예: 9d850d65-219f-11e6-b752-08002702c825:33) • Server UUID 값은 SHOW VARIABLES LIKE ‘server_uuid‘로 확인 가능 GTID SET • GTID의 집합 (예: 9d850d65-219f-11e6-b752-08002702c825:1-33:38-42) EXECUTED GTID ★ • 초기화 이후 실행된 GTID SET을 의미하며, gtid_executed 시스템 변수에서 확인 가능 • Binary Log를 남기는 Master 입장에서는 자신의 GTID 발급 현황을, Slave 입장에서는 Master의 트랜잭션이 어디까지 반영되었는지를 의미하기도 함 PURGED GTID • 실행 후 Binary Log Purge까지 완료된 GTID SET을 의미하며, gtid_purged 시스템 변수에서 확인 가능 • Slave가 gtid_purged 범위의 GTID를 요청하면 해당 요청은 처리 불가 ※ gtid_executed, gtid_purged 시스템 변수 값은 DB 재기동 시점에 계산되어 초기화 MySQL GTID 시작하기 2 / 15
  • 4.
    GTID를 이해하기 위한기본 개념(I) mysql-bin.002 mysql-bin.003 mysql-bin.004 mysql-bin.001 Binary Log Purge 9d850d65-219f-11e6-b752-08002702c825:1-30 9d850d65-219f-11e6-b752-08002702c825:31-81 9d850d65-219f-11e6-b752-08002702c825:82-102 9d850d65-219f-11e6-b752-08002702c825:103-114 Purged Gtid 9d850d65-219f-11e6-b752-08002702c825:1-81 Executed Gtid 9d850d65-219f-11e6-b752-08002702c825:1-114 Slave 전파 복제되어 처리되는 트랜잭션에 의해 Slave DB에서도 동일한 Executed GTID 값을 가지게 됨 MySQL GTID 시작하기 3 / 15
  • 5.
    주제1. IO Thread와SQL Thread에게 GTID란? (1) IO Thread에게 GTID란? • IO Thread가 초기화(change master) 될 때 Master에서 어떤 Log를 받아와야 될지 판단하는 기준 • “Master의 Executed GTID – 자신의 Executed GTID 영역”을 받아와서 Relay Log에 저장 • Master의 Executed GTID : 9d850d65-219f-11e6-b752-08002702c825:1-102 • 자신의 Executed GTID : 9d850d65-219f-11e6-b752-08002702c825:1-90:96-100 • Relay Log로 가져오게 되는 트랜잭션은 9d850d65-219f-11e6-b752-08002702c825:91-95:101-102 • IO Thread 초기화 이후에는 non-GTID 모드와 동일하게 Binary Log File / Position 기반으로 동작 (2) SQL Thread에게 GTID란? • SQL Thread는 non-GTID 모드와 동일하게 Relay Log에 저장된 트랜잭션을 순차 처리함 • 다만, GTID 모드에서는 SQL Thread가 실행하는 GTID 트랜잭션의 기록만 추가로 남김 (gtid_executed) ※ GTID는 IO Thread가 초기화 될 때 Master의 Binary Log File/Position을 찾기 위해 사용됨 그리고 필요할 때 쓰기 위해 SQL Thread가 동작할 때 실행된 GTID에 대한 기록을 남김 이외의 기본적인 Replication 동작은 GTID나 non-GTID나 동일함 MySQL GTID 시작하기 4 / 15
  • 6.
    주제2. log-bin /log-slave-updates 옵션의 사용 (1) 5.6 버전과 5.7 버전의 요구사항이 다르다. • 5.6 버전까지 GTID를 사용하기 위해서는 복제 그룹의 모든 DB가 log-bin / log-slave-updates 옵션을 사용해야 함 • 누구나 Master가 될 수 있다는 기본적인 GTID 컨셉을 충족하기 위함 • 복제된 트랜잭션이 어디까지 수행되었는지 기록을 해야 하기 때문 • DB 재기동 시점에 Local에 저장된 첫번째, 마지막 Binary Log를 읽어 gtid_purged, gtid_executed 값을 계산 • 5.7 버전부터는 log-bin / log-slave-updates 옵션의 사용은 필수가 아님 • log-bin / log-slave-updates 옵션을 사용하지 않으면 mysql.gtid_executed 테이블에 필요한 정보를 저장 • 단, Master 역할을 부여받을 가능성이 있는 DB는 반드시 log-bin / log-slave-updates 옵션을 켜 두어야 함 MySQL GTID 시작하기 5 / 15
  • 7.
    주제2. log-bin /log-slave-updates 옵션의 사용 (2) log-bin / log-slave-updates 옵션 사용시 유의할 점은? • MySQL 데몬이 재기동 되는 경우 gtid_executed 값은 아래의 정보를 참조하여 초기화 됨 • mysql.gtid_executed 테이블에 저장된 GTID 값 ”binary log switch 시점에 1회 업데이트” • Local에 남겨진 마지막 binary log의 GTID 값 • Binary Log 저장 안정성(sync_binlog) 확보 실패 혹은 임의 삭제 시 gtid_executed 변수의 잘못된 초기화를 유발 <사례> Slave MySQL 데몬 crash 후 binary log를 유실한 상황 mysql-bin.003 mysql-bin.004 9d850d65-219f-11e6-b752-08002702c825:82-102 9d850d65-219f-11e6-b752-08002702c825:103-114 mysql.gtid_executed 테이블 9d850d65-219f-11e6-b752-08002702c825:1-102 9d850d65-219f-11e6-b752-08002702c825:113-114 트랜잭션의 Binary Log flush 실패(유실) slave> show global variables like 'gtid_executed'; +---------------+----------------------------------------------------+ | Variable_name | Value | +---------------+----------------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-112:115-240 | +---------------+----------------------------------------------------+ master> show global variables like 'gtid_executed'; +---------------+--------------------------------------------+ | Variable_name | Value | +---------------+--------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-240 | +---------------+--------------------------------------------+ ??? MySQL GTID 시작하기 6 / 15
  • 8.
    주제2. log-bin /log-slave-updates 옵션의 사용 7 / 15 (2) log-bin / log-slave-updates 옵션 사용시 유의할 점은? • Slave DB의 gtid_executed 값에 빈 구간(113-114)이 발생 • 하지만 복제는 여전히 잘 되고, 데이터 정합성에도 전혀 문제가 없음 • 당장 문제가 없는 것은 GTID 복제 역시 Log File / Position 기반으로 동작하기 때문 ”mysql.slave_relay_log_info” • IO Thread가 초기화 되는 시점에 “Master의 Executed GTID – Slave의 Executed GTID 영역”을 받아와서 Relay Log 에 저장하게 되며 문제는 여기서 발생하게 됨 Case 1) GTID 113-114 트랜잭션이 이미 Master에서 Purge 되고 남아있지 않은 경우  복제 연결 불가 Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.‘ Case 2) GTID 113-114 트랜잭션이 Master에 남아있는 경우  중복 실행 (데이터 정합성 문제 혹은 복제 에러 발생) slave> show global variables like 'gtid_executed'; +---------------+----------------------------------------------------+ | Variable_name | Value | +---------------+----------------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-112:115-240 | +---------------+----------------------------------------------------+ master> show global variables like 'gtid_executed'; +---------------+--------------------------------------------+ | Variable_name | Value | +---------------+--------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-240 | +---------------+--------------------------------------------+ ??? MySQL GTID 시작하기 ???
  • 9.
    주제2. log-bin /log-slave-updates 옵션의 사용 8 / 15 (2) log-bin / log-slave-updates 옵션 사용시 유의할 점은? • 문제가 생기기 전에 보정 필요 • 방안1) 누락된 트랜잭션을 Empty 트랜잭션으로 Skip 처리 • 방안2) Slave의 gtid_executed 값을 적절히 변경 slave> show global variables like 'gtid_executed'; +---------------+----------------------------------------------------+ | Variable_name | Value | +---------------+----------------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-112,115-240 | +---------------+----------------------------------------------------+ ??? slave> STOP SLAVE SQL_THREAD; slave> SET GTID_NEXT='9d850d65-219f-11e6-b752-08002702c825:113'; slave> BEGIN; COMMIT; slave> SET GTID_NEXT='AUTOMATIC'; slave> START SLAVE SQL_THREAD; slave> STOP SLAVE SQL_THREAD; slave> show global variables like ‘gtid_executed’; … '9d850d65-219f-11e6-b752-08002702c825:285’ … slave> RESET MASTER; slave> SET GLOBAL GTID_PURGED='9d850d65-219f-11e6-b752-08002702c825:1-285'; slave> START SLAVE SQL_THREAD ; MySQL GTID 시작하기
  • 10.
    주제2. log-bin /log-slave-updates 옵션의 사용 9 / 15 (3) log-bin / log-slave-updates 옵션을 사용하지 않은 경우 유의할 점은? • 트랜잭션 당 1건의 Record가 mysql.gtid_executed 테이블에 Insert • N 건(기본 1000)의 Record가 쌓이면 N건을 Delete 하고 1건의 Record를 Insert (gtid_executed table compression) • mysql.gtid_executed 테이블은 InnoDB 테이블이므로, ACID transaction 처리가 가능하므로 유실은 발생하지 않음 • MySQL 데몬이 재기동 되는 경우 gtid_executed 값은 mysql.gtid_executed 테이블의 값을 참조하여 초기화 됨 9d850d65-219f-11e6-b752-08002702c825 1000 1000 9d850d65-219f-11e6-b752-08002702c825 1001 1001 … 9d850d65-219f-11e6-b752-08002702c825 2000 2000 복제된 트랜잭션 1건당 1 Record 생성 9d850d65-219f-11e6-b752-08002702c825 1 1000 9d850d65-219f-11e6-b752-08002702c825 1001 1001 … 9d850d65-219f-11e6-b752-08002702c825 2000 2000 9d850d65-219f-11e6-b752-08002702c825 1 2000 압축된 결과 저장 삭제 MySQL GTID 시작하기
  • 11.
    주제2. log-bin /log-slave-updates 옵션의 사용 10 / 15 (3) log-bin / log-slave-updates 옵션을 사용하지 않은 경우 유의할 점은? • 여기서 잠깐!!! InnoDB에 대량의 Insert, Delete 작업이 복제 트랜잭션 건수만큼 추가 • InnoDB 테이블의 기본적인 IO 메커니즘을 따르므로, 대량의 insert / delete에 따른 부하가 추가됨 • Master의 변경량이 많아진다면? ※ mysql.gtid_executed 테이블의 압축에 대한 로직은 MySQL Reference Manual에 잘못 설명이 되어 있음 Manual : log-bin 설정에 따라 다른 동작  실제 : log-bin / log-slave-updates 설정 따라 다른 동작 gtid_executed INSERT 1 Row redo undo Compression DELETE N Rows INSERT 1 Row Purge Old Trx ---TRANSACTION 14349675830, ACTIVE 4787 sec fetching rows mysql tables in use 1, locked 1 1766093 lock struct(s), heap size 189702352, 23552816 row lock(s), undo log entries 23552812 MySQL thread id 2, OS thread handle 140153037256448, query id 0 Compressing gtid_executed table ------------ TRANSACTIONS ------------ Trx id counter 19540270802 Purge done for trx's n:o < 17490950910 undo n:o < 0 state: History list length 1024727771 MySQL GTID 시작하기
  • 12.
    주제3. 백업 데이터로복구 11 / 15 Nothing Special !! • IO Thread가 적절하게 Binary Log를 가져올 수 있도록 gtid_executed 값을 설정해 주면 됨 • mysqldump, xtrabackup 등의 도구에서 남겨준 gtid_executed 값을 참조하거나, 운영자가 직접 확인 • 신규 서버에 데이터 복구가 완료된 후 • GTID_EXECUTED 시스템 변수는 READ ONLY !!! RESET MASTER로 GTID 초기화 후 GTID_PURGED 값을 설정 (GTID_EXECUTED 값은 자동으로 설정) • 만약 Multi Source Replication을 사용하는 Slave라서 Master DB가 여러 대라면? mysql> SET GLOBAL GTID_EXECUTED='9d850d65-219f-11e6-b752-08002702c825:1-2000'; ERROR 1238 (HY000): Variable 'gtid_executed' is a read only variable ??? mysql> RESET MASTER; mysql> SET GLOBAL GTID_PURGED='9d850d65-219f-11e6-b752-08002702c825:1-2000'; mysql> RESET MASTER; mysql> SET GLOBAL GTID_PURGED='9d850d65-219f-11e6-b752-08002702c825:1-2000, a17a1326-219f-11e6-88f7-080027ee5436:1-520’; MySQL GTID 시작하기
  • 13.
    주제4. Reset Master의역습 12 / 15 • Non-GTID 복제에서 Slave DB에서 수행하는 Reset Master는 복제에 아무런 영향을 주지 않음 • Reset Master 커맨드는 gtid_executed 시스템 변수를 초기화 시키기 때문에, GTID 복제에서 문제를 일으킴 • IO Thread가 초기화 될 때 문제가 발생하므로, 앞서 다뤘던 방법을 참고하여 보정 작업 필요 slave> reset master; … slave> show global variables like 'gtid_executed'; +---------------+----------------------------------------------+ | Variable_name | Value | +---------------+----------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:225-240 | +---------------+----------------------------------------------+ master> show global variables like 'gtid_executed'; +---------------+--------------------------------------------+ | Variable_name | Value | +---------------+--------------------------------------------+ | gtid_executed | 9d850d65-219f-11e6-b752-08002702c825:1-240 | +---------------+--------------------------------------------+ ??? MySQL GTID 시작하기
  • 14.
    GTID를 이해하기 위한기본 개념(II) 13 / 15 GTID_MODE • GTID 발급 여부와 GTID를 부여받지 않은 트랜잭션(Anonymous Transaction)의 허용 여부를 결정 • 5.6 버전 기준으로 ON / OFF 2가지 모드가 존재 • 5.7 버전 기준으로 OFF ↔ OFF_PERMISSIVE ↔ ON_PERMISSIVE ↔ ON 4가지 모드가 존재, 단계별 변경만 가능 <GTID MODE 호환표> Master Slave OFF OFF_PERMISSIVE ON_PERMISSIVE ON OFF Y Y N N OFF_PERMISSIVE Y Y Y Y ON_PERMISSIVE Y Y Y Y ON N N Y Y MySQL GTID 시작하기 ON OFF (empty) PERMISSIVE Master 입장에서의 동작 ON : GTID 부여 OFF : GTID 부여하지 않음 Slave 입장에서의 동작 PERMISSIVE : GTID/Anonymous 혼재 허용
  • 15.
    주제5. GTID MODE온라인 변경 14 / 15 5.7 버전에서 지원 https://dev.mysql.com/doc/refman/5.7/en/replication-mode-change-online-enable-gtids.html 1. 복제 그룹 내 모든 서버의 ENFORCE_GTID_CONSISTENCY 값을 ON 으로 변경한다. GTID 환경에서 지원되지 않는 SQL을 사전에 검출하기 위함 원칙적으로는 해당 변수 값을 WARN으로 먼저 변경하여 문제가 발생하는 경우 Warning을 발생시키도록 함 장기간 모니터링 후 문제가 없다는 것을 확인하고, ON으로 변경해야 함 2. 복제 그룹 내 모든 서버의 GTID_MODE 값을 OFF_PERMISSIVE로 변경한다. GTID가 부여된 트랜잭션이 넘어와도 처리할 수 있도록 하기 위함 3. 복제 그룹 내 모든 서버의 GTID_MODE 값을 ON_PERMISSIVE로 변경한다. Master DB는 GTID가 부여하기 시작하고, Slave DB는 GTID 발급 여부와 관계없이 트랜잭션을 처리한다. 4. 잔여 Anonymous 트랜잭션 확인 모든 DB 노드에서 SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT‘ 결과 값을 확인 결과 값이 0인 상태가 한번이라도 보이면 OK 5. 복제 그룹 내 모든 서버의 GTID_MODE 값을 ON으로 변경한다. 더 이상 GTID가 발급되지 않은 트랜잭션은 존재하지 않음 6. Binary Log File / Position 기반으로 동작하던 복제를 Auto Position 모드로 변경한다. STOP SLAVE; CHANGE MASTER TO MASTER_AUTO_POSITION=1; START SLAVE; MySQL GTID 시작하기
  • 16.
    주제5. GTID MODE의혼용 15 / 15 5.7 버전에서만 가능 MySQL GTID 시작하기 Group 1 (GTID) 분석/통계 작업용 DB (DW) - Multi Source Replication 구성 GTID_MODE = OFF_PERMISSIVE Slave가 OFF_PERMISSIVE인 경우 GTID_MODE=ON/OFF인 DB를 모두 Master로 인식할 수 있다. Group 2 (GTID) channel 1 channel 2 Group 3 (non-GTID) channel 3
  • 17.