본문 바로가기

DBA 이야기

MySQL 5.7 GTID

GTID(Global Transaction Identifiers)

  • GTID를 사용하게 되면, 각각의 트렌젝션들은 고유한 전역식별자를 갖게 된다

  • master 서버에서 수행된(commited) 트랜젝션들이 slave 서버(들)에 적용되어 지는 것에대한 추적 또한 쉽다.

  • 새로운 Slave의 추가 구성이나, 신규 Master로 Failover 할 때에도, binary log files와 postion의 확인은 중요하지 않고, 작업 역시 간단해 진다.

  • GTID 기반 복제는 완전히 트랜젝션 기반이기 때문에, Master와 Slave 간의 일관성 확인이 간단하다.

  • GTID 기반 복제는 Statement-based replication과 row-based replication을 모두 지원한다.

    그러나 최고의 결과를 얻기위해서는, row-based replication을 권장한다.


MySQL 5.6에서는 MySQL Cluster(NDB storage engine)에서 GTID 사용은 안전하지 않으며 MySQL Cluster 환경에서 GTID를 사용할 수는 있으나, 

NDB와 Replication에서 쉽게 문제가 발생할 수 있다고 경고를 하였다. 하지만 MySQL 5.7에서는 이 경고 문구가 사라졌다.



GTID 컨셉

  • GTID (Global Transaction Identifier)
  • master 서버에서 commit 된 트랜잭션과 연관된 유일한 식별자로 생성됨
  • 연관된 모든 서버에서 유일한 식별자이며, 모든 트랜잭션과 GTID 들은 1:1 관계이다.
  • souce_id, transaction_id로 구성되어있고 (:)로 나뉘어져있음.
GTID = source_id:transaction_Id
  • source_id는 서버 식별자 (server_uuid)

server-uuid는 Mysql datadir 하단의 auto.cnf파일에 명시되어 있다.


  • transaction_id는 해당 서버에서 커밋된 트랜잭션의 순서에 따라 순차적인 숫자로 결정된다.
    예로 첫 번째 트랜잭션은 transaction_id=1이 되고, 동일한 서버에서 열 번째 트랜잭션은 transaction_id=10이 된다.
    (GTID에서 트랜잭션이 순차적인 숫자는 1부터 시작된다. 0은 될 수 없다.)
  • 서버 id (UUID)가 3E11FA47-71CA-11E1-9E33-C80AA9429562인 23번째 트랜잭션은 GTID가 아래와 같다.
3E11FA47-71CA-11E1-9E33-C80AA9429562:23
  • GTID는 binary log 뿐만 아니라, SHOW SLAVE STATUS 구문에서도 확인 가능하다.
  • mysqlbinlog --base64-output=DECODE-ROWS 문장으로 log file에서 확인하거나 SHOW BINLOG EVENTS의 결과에서도 볼 수 있다.
  • SHOW MASTER STATUS나 SHOW SLAVE STATUS 명령의 결과와 같이, 동일 서버에서 생긴 GTID의 순서는 단문으로 축소되어 아래와 같이 보여진다.
3E11FA47-71CA-11E1-9E33-C80AA9429562:1-5

==> server_uuid가 3E11FA47-71CA-11E1-9E33-C80AA9429562인 서버에서 생성된 다섯 번째 트랜잭션을 통한 첫 번째를 나타낸다.

  • MySQL 5.6.6 이후에는 START SLAVE 옵션인 SQL_BEFORE_GTIDS와 SQL_AFTER_GTIDS 변수를 제공한다.

  • GTID SET
    gtid_set:
         uuid_set [, uuid_set] ...
         | ''
    
    uuid_set:
         uuid:interval[:interval]...
    
    uuid:
         hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh
    
    h:
        [0-9|A-F]
    
    interval:
         n[-n]
    
        (n >= 1)  


  • GTID set은 MySQL 서버에서 여러 방법으로 사용된다.

    예를들면, gtid_executed, gtid_purged system variables로 값이 저장된 것들이 GTID set으로 표현된다. 
    GTID_SUBSET() 함수와 GTID_SUBTRACT() 함수는 GTID sets 입력값을 필요로 한다.
    GTID sets는 알파벳순, 병합된 숫자 간격 그리고 오름차순으로 서버 변수에서 보여진다.

  • GTID는 항상 master와 slave 사이에서 보존된다. 이 의미는, 당신이 언제나 binary log를 검사하여 어떤 트랜젝션이 어느 slave에 적용됐는지 판별할 수 있음을 의미한다.

  • 주어진 서버에서 커밋된 GTID를 가진 트랜잭션은 이미 수행한 동일한 GTID를 가진 트랜잭션은 서버에서 무시된다.
    결과적으로 master 서버에서 commit 된 트랜잭션은 한 번 이상 slave에 적용되지 않으며, 이는 일관성을 보장한다.

  • GTID를 사용할 때, slave는 master에 있는 파일 이름과 해당 파일의 포지션과 같은 로컬에서 확인할 수 없는 데이터가 전혀 필요하지 않다.
  • master와 싱크를 위한 모든 필요한 정보는 replication data streadm으로 부터 받는다.
  • GTID는 master와 slave 사이의 복제를 시작, 중지, 재개하는데 중요포인트 였던 file-offset pairs을 대신한다.
    따라서, master 서버로 부터 복제를 위해 slave 서버에서 사용되던 CHANGE MASTER TO 구문에 MASTER_LOG_FILE, MASTER_LOG_POS 옵션이 포함되지 않는다.  
    대신에 단지 MASTER_AUTO_POSITION 옵션을 활성화 하는 것으로 충분하다.
    GTID를 기반으로하는 replication을 사용할 경우, master와 slave를 시작하고 설정하려면 아래 url을 참고한다.
    GTID를 이용한 복제 구성(원문)

  • GTID의 생성 및 주기는 다음과 같은 스텝으로 진행된다.

    1. Master에서 실행되고 커밋된 트랜잭션
    • 이 트랜잭션은 master의 UUID와 아직 사용되지 않은 0이 아닌 가장 작은 트랜잭션 순차 숫자를 사용한 GTID로 할당된다.
      GTID는 Master 서버의 binary log에 쓰여진다.(log내에서 즉시 트랜잭션 자체 선행)

          2. binary log 데이터가 slave로 이동되고 slave의 relay log로 저장된 후 (해당 메커니즘은 아래 url을 참고한다.)
     Section 17.2, “Replication Implementation(원문)

              slave는 GTID를 읽고, 해당 값으로 gtid_next 시스템 변수 값을 설정한다.
              이는 slave 다음 트랜잭션도 반드시 해당 GTID를 사용해 로깅 되어야 하는 것을 뜻한다. 

              slave session 문장에 gtid_next를 셋팅하는 것이 중요한다.

          3. slave는 이 GTID가 이미 자신의 바이너리 로그에 있는 트랜잭션을 기록하는데 사용되지 않았음을 검증한다.
              만일 GTID가 사용되지 않았다면, slave는 GTID를 쓰고 트랜잭션을 적용한다.(그리고 binary log에 트랜잭션을 작성한다.)
              트랜잭션을 실행하기 전에 트랜잭션의 GTID를 먼저 읽고 체크하는 것은, 아직 커밋되거나 적용되지 않은 트랜잭션에 대해 slave가 해당 GTID를 가진 이전 트랜잭션이 slave에 적용되지 않았음과
              다른 세션이 해당 GTID를 읽지 않았음을 보장하는 것이다.  

              다른 말로 여러개의 클라이언트는 동일한 트랜잭션을 동시 적용이 허용되지 않음을 뜻한다.

          4. gtid_next 값이 비어있지 않아서, slave는 이 트랜잭션에 대한 GTID를 생성하려고 시도하지 않는 대신, 
              이 변수에 GTID를 저장한다. -이는 master로부터 획득한 GTID - binary log 내에 트랜잭션을 즉시 선행한다.     



  • mysql.gtid_executed Table (Mysql 5.7.5 에서 추가됨)
  • GTIDs는 mysql DB의 gtid_executed 테이블에 저장이 된다.
  • gtid_executed 테이블에는 master server의 UUID와 set의 트랜젝션 IDs의 시작 및 종료 값을 포함한다.(오직 단일 GTID를 참조하는 행에 대해)
  • 이것들은의 마지막 2개의 값은 같다.
  • mysql.gtid_executed 테이블은 MySQL Server를 설치하거나, 엔진 upgrade를 하면 아래의 구문을 사용하여, 생성된다.

    CREATE TABLE gtid_executed (
        source_uuid CHAR(36) NOT NULL,
        interval_start BIGINT(20) NOT NULL, 
        interval_end BIGINT(20) NOT NULL,                                                                                                                                                                                    
        PRIMARY KEY (source_uuid, interval_start)
    )     


    다른 MySQL system 테이블들처럼, 테이블을 임의로 생성하거나, 변경하면 안됩니다.


  • GTIDs는 gtid_mode가 ON 또는 ON_PERMISSIVE 모드일 때만, mysql.gtid_executed 테이블에 저장된다.
  • GTIDS는 binary loging의 enable 여부와 상관없이 저장이 된다.그러나 log_bin 옵션이 ON인지 OFF인지에 따라 다르게 저장이 된다.
  • binary logging이 disable(log_bin = OFF)이면, 테이블에 트랜젝션과 함께 각 트랜젝션에 속하는 GTID를 저장한다.
    또한, 사용자가 설정가능한 주기로 gtid_executed 테이블을 압축한다. 제세한 정보는 하단의 mysql.gtid_executed 테이블 압축을 참조.
  • binary logging이 enable(log_bin = ON)이면, binary log가 rotate되거나, 서바가 종료될때 mysql.gtid_exeucted 테이블에 저장될 뿐만 아니라,
    서버는 새로운 바이너리 로그안에 이전 바이너리 로그에 기록된 모든 트랜잭션에 대한 GTIDs를 기록한다.
    예기치 않게 서버가 중지된 경우, 이전 바이너리 로그에서 GTIDs set은 mysql.gtid_executed 테이블에 저장되지 않는다. 이런 경우, 이러한 GTIDs는
    복구 동안 테이블과 gtid_executed 시스템 변수에 추가된다.
  • mysql.gtid_executed 테이블은 RESET MASTER 구문으로 초기화 된다. 
mysql.gtid_executed 테이블 압축
  • 시간이 흐르면, mysql.gtid_executed 테이블은 아래의 보여지는 것처럼, 동일 서버에서 발생하는 순차적인 트랜젝션 IDs를 까진 개별 GTID 값으로 가득 찰 수도 있다.

    mysql> SELECT * FROM mysql.gtid_executed;
    +--------------------------------------+----------------+--------------+
    | source_uuid                          | interval_start | interval_end |
    |--------------------------------------+----------------+--------------|
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37             | 37           |
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 38             | 38           |
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 39             | 39           |
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 40             | 40           |
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 41             | 41           |
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 42             | 42           |
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 43             | 43           |
    ...


  • 각각의 GTID set을  트랜젝션 식별자 전체 간격을 1줄로 대체하는 방법으로 주기적으로 해당 테이블을 압축한다면, 저장 공간을 절약 할 수 있다.

    +--------------------------------------+----------------+--------------+
    | source_uuid                          | interval_start | interval_end |
    |--------------------------------------+----------------+--------------|
    | 3E11FA47-71CA-11E1-9E33-C80AA9429562 | 37             | 43           |
    ...


  • GTIDs가 enable 일 때, 서버는 mysql.gtid_executed 테이블을 정기적으로 압축한다.
  • 테이블이 압축되기전에, 트랜잭션을 체크하지 않는 것으로 트랜잭션 수를 제어할 수 있다.
  • executed_gtids_compression_period 시스템 변수로 압축률을 설정할 수 있다. 기본 값은 1000이며, 이것은 각 1000개의 트랜잭션이 수행됐을 때 마다, 압축이 된다는 의미이다.
    executed_gtid_compression_period 값을 0으로 두면 압축을 하지 않는다. 이렇게 설정을 하게 되면, gtid_executed 테이블에 주기적으로 저장되는 값들로 인해 많은 공간을 차지하게 될 것이다. 

    binary logging이 enable이면, executed_gtids_compression_period값은 사용되어지지 않으며, mysql.gtid_executed 테이블은 매 binary log 파일의 rotation이 수행 될 때, 압축 된다.


  • GTIDs 기능을 enable하면, 전용 forground 쓰레드가 생성된다. mysql.gtid_executed 테이블은 그 쓰레드에 의해 압축이 된다.

  • 이 쓰레드는 SHOW PROCESSLIST의 결과에는 보이지 않으나, 아래의 thread 테이블에서 확인할 수 있다.

    mysql> SELECT * FROM PERFORMANCE_SCHEMA.THREADS WHERE NAME LIKE '%gtid%'\G
    *************************** 1. row ***************************
              THREAD_ID: 21
                   NAME: thread/sql/compress_gtid_table
                   TYPE: FOREGROUND
         PROCESSLIST_ID: 139635685943104
       PROCESSLIST_USER: NULL
       PROCESSLIST_HOST: NULL
         PROCESSLIST_DB: NULL
    PROCESSLIST_COMMAND: Daemon
       PROCESSLIST_TIME: 611
      PROCESSLIST_STATE: Suspending
       PROCESSLIST_INFO: NULL
       PARENT_THREAD_ID: 1
                   ROLE: NULL
           INSTRUMENTED: YES


  • thread/sql/compress_gtid_table이란 이름의 이 쓰레드는, 평소에는 sleep 상태이다가, 위에 언급한 것 처럼 mysql.gtid_executed 테이블을 executed_gtids_compression_period 기간이 
    되면 wake up하여, 테이블 압축을 수행한다. 
  • 이 쓰레드는 executed_gtids_compression_period 기간이 오기 전까지 sleep 상태였다가 wake up이 되어 압축을 수행하고를 무한히 반복한다.
  • binary logging이 disable이고 executed_gtids_compression_preiod의 설정 값이 0이면, 해당 쓰레드는 영원히 sleep 상태가 된다.

GTID를 이용한 복제 구성

MySQL 5.7의 GTID 기반 복제를 구성하고 시작하는 방법을 설명한다.
아래 방법은 master를 중지할 수 있다는 가정하의 방법이다. (cold start)

(1 master와 1 slave로 구성하는 방법)

<초기 설정>

  1. 만약 이미 replication이 동작 중 이라면, master와 slave를 read-only로 변경하여 동기화를 완료시킨다.
  2. 동기화 완료 후에, 2개의 db를 중지 시킨다.
  3. GTIDs를 enable하고 옵션을 설정한 후 master와 slave를 restart를 한다
    (mysqld options들에 표기해야되는 옵션들은 뒤에서 다시 설명한다.)
  4. master의 복제된 데이터를 가지고 slave를 구축하고, auto-positioning을 사용하여, 복제를 시작한다.
    (이 단계를 위해 필요한 구문은 뒤에 다시 설명한다.)
  5. data update가 가능하게 하기위하여, master와 slave의 read-only mode를 disable한다.


<GTID 설정> (대부분은 MySQL의 루트 계정 또는  SUPER 권한을 가진 MySQL 사용자 계정을 필요로 한다.)


1. 복제를 위한 계정을 생성해 준다.

mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'replpassword';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'

2. master의 configure 파일에 복제용 옵션을 넣는다.

[mysqld]
log-bin=mysql-bin
server-id=1




  1. 단계 : master 서버와 slave 서버를 동기화 한다. 
    이와 같은 진행을 위해서 두 서버를 read_only로 변경할 수 있다.

    mysql>SET @@global.read_only=ON;

    수행 후 Slave 서버가 master의 동기화를 완젼히 따라간 것을 확인한다.

  2. 단계 : 두 서버를 중지한다. mysqladmin tool을 사용하여 각 서버를 중지 시킨다. 

    shell>mysqladmin -uusername -p shutdown


  3. 단계 : GTIDs 설정을 enable하고 두 서버를 restart합니다. 
    GTID-based replication을 사용하기 위해서, GTID mode, binary logging, slave update loggin enable등을 활성화 시킵니다. 
    (활성화 시, GTID-based replication을 사용하지 않으면 안전하지 않다는 문구를 볼 수 있습니다.) 
    또한, 원치 않은 data update를 방지하기 위해서 두 서버 모두 read-only mode로 시작하기를 권고합니다.
    아래의 구문으로 시작하면 됩니다. 

    shell> mysqld_safe --gtid_mode=ON --log-bin --log-slave-updates --enforce-gtid-consistency & 


    MySQL 5.6.9이전 버전에서는 --enforce-gtid-consistency옵션이 --disable-gtid-unsafe-statements 였습니다.

    또한 slave 서버를 시작할 때, --skip-slave 옵션을 추가로 주어야 합니다.


    --gtid-mode는 boolean 형식도 enumeration(enum) 형식도 아닙니다. 오직 ON 또는 OFF 값만을 사용합니다. 숫자값 0이나 1을 사용하면 예기치 않은 결과가 발생할 수도 있습니다.


  4.  단계 : Slave가 Master로 연결하기 위한 설정을 해주어야 합니다.
     이미 master, slave 구성이 되어 있던 서버라면 몇몇의 설정은 제외하여도 됩니다. 

    mysql> CHANGE MASTER TO 
         >     MASTER_HOST = host,
         >     MASTER_PORT = port,
         >     MASTER_USER = user,
         >     MASTER_PASSWORD = password,
         >     MASTER_AUTO_POSITION = 1;

    MASTER_AUTO_POSITION=1 사용으로 MASTER_LOG_FILE 옵션과 MASTER_LOG_POS 옵션이 대체됩니다.
    CHANGE MASTER TO 구문이 성공하면 slave 서버에서 start slave를 수행합니다.

  5. 단계 : read-only mode를 disable합니다. master에서 data를 update 가능하게 하기위해 아래의 명령을 사용합니다. 

    mysql> SET @@global.read_only = OFF;



[mysqld]
...
binlog-format=MIXED
log-bin
log-slave-updates=true
gtid-mode=on 
enforce-gtid-consistency=true 
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
binlog-checksum=CRC32
master-verify-checksum=1
server-id=1
report-host=black


 [mysqld]
...
binlog-format=MIXED
log-slave-updates=true
log-bin
gtid-mode=on 
enforce-gtid-consistency=true 
master-info-repository=TABLE
relay-log-info-repository=TABLE
sync-master-info=1
slave-parallel-workers=2
binlog-checksum=CRC32
master-verify-checksum=1
slave-sql-verify-checksum=1
binlog-rows-query-log_events=1
server-id=2
report-host=white



GRANT REPLICATION SLAVE ON *.* TO repl@'%' IDENTIFIED BY 'repl'; 
FLUSH PRIVILEGES;


CHANGE MASTER TO MASTER_HOST='192.168.xxx.xxx', MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_AUTO_POSITION=1;
START SLAVE;


-- 복원 포맷

# at 278
#141016 16:23:22 server id 1122  end_log_pos 386 CRC32 0x3d258216  Query thread_id=49 exec_time=0   error_code=0
use `test`/*!*/;
SET TIMESTAMP=1413444202/*!*/;
insert into mha_command values(13)
/*!*/;
# at 386
#141016 16:23:22 server id 1122  end_log_pos 417 CRC32 0xcfb7cc33  Xid = 297979
COMMIT/*!*/;
# at 417
#141016 16:34:03 server id 1122  end_log_pos 465 CRC32 0x54631d4e  GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '12f054f8-d036-11e3-9092-064ee00000ad:2'/*!*/;
# at 465
#141016 16:34:03 server id 1122  end_log_pos 544 CRC32 0xc81932b8  Query thread_id=51 exec_time=0   error_code=0
SET TIMESTAMP=1413444843/*!*/;
BEGIN
/*!*/;
# at 544
#141016 16:34:03 server id 1122  end_log_pos 652 CRC32 0x1496978b  Query thread_id=51 exec_time=0   error_code=0
SET TIMESTAMP=1413444843/*!*/;
insert into mha_command values(14)
/*!*/;
# at 652
#141016 16:34:03 server id 1122  end_log_pos 683 CRC32 0xc422daf1  Xid = 297985
COMMIT/*!*/;
# at 683
#141016 16:34:04 server id 1122  end_log_pos 731 CRC32 0x604006cc  GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '12f054f8-d036-11e3-9092-064ee00000ad:3'/*!*/;


-- MySQL dump 10.13  Distrib 5.6.15, for linux-glibc2.5 (x86_64)
--
-- Host: localhost    Database: test
-- ------------------------------------------------------
-- Server version       5.6.15-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= 0;

--
-- GTID state at the beginning of the backup
--

SET @@GLOBAL.GTID_PURGED='12f054f8-d036-11e3-9092-064ee00000ad:1-28,
cb01baa8-f2c0-11e3-b1cf-069766000131:1-148541';

--
-- Table structure for table `mha_command`
--

DROP TABLE IF EXISTS `mha_command`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `mha_command` (
  `col1` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `mha_command`
--




GTID를 이용한 장애복구와 Scaleout


GTID 복제의 제약사항

 

  1. 한 구문에서 MyISAM 같은 nontransaction egine의 테이블과 InnoDB 같은 transactional storage engined의 테이블을 섞어서 사용할 수 없다.(Slave에서 결과값이 다르게 나올 수 있기 때문에)
  2. CREATE TABLE ... SELECT 구문은 GTID-based replication에서 지원하지 않는다. (일관성 문제) 
    → (Create Table; , Insert into Table ..Select구문 2개로 나눠어서 실행하면 됨)
  3. CREATE TEMPORARY TABLE과 DROP TEMPORARY TABLE 구문은 GTID-based replication에서 지원하지 않는다. (일관성 문제)
  4. 지원되지 않는 명령문의 실행을 방지하기 위해, 모든 서버가 --enforce-gtid consistency 옵션을 사용하여 시작해야 하며, 이로 인해
    위의 문제가 되는 명령문 들이 수행되지 않도록 한다. 
  5. GTIDs를 사용하는 경우 SQL_SLAVE_SKIP_COUNTER 구문은 지원하지 않는다. 만약 transaction skip이 필요할 경우, Injecting empty transactions을 사용해서 처리 할 수 있다.
  6. GTID mode의 replication에서 GTID 값이 없는 binary log를 만들어 mysqldump를 사용하여 import하는 것이 가능합니다.
  7. GTID mode와 mysql_upgrade. GTID mode를 사용하는 MySQL Sever에서 mysql_upgrade를 사용하는 것을 추천하지 않는다.
    mysql_upgrade가 nontransactional MyISAM 스토리지 엔진을 사용하는 system 테이블들을 변경할 수 있기 때문이다. 


MySQL 5.7 GTID vs Maria 10.x GTID