專職DBA-MySQL基於GTID的複製 GTID(global transaction identifier)是一個在數據庫上對每一個已經提交到數據庫的事務的惟一編號。 GTID = server_uuid:gtid GTID複製的工做原理: (1).當主庫進行數據更新時,會在事務前產生gtid號,一同記錄到binlog日誌中。 (2).從庫端的I/O線程將變動的binlog數據,寫入到本地的中繼日誌relay log中。 (3).從庫端的SQL線程從中繼日誌中獲取gtid號,而後對比本地的binlog查看是否有記錄。若是有記錄,說明該gtid的事務已經執行,此時從庫會忽略。 (4).若是沒有記錄,則從庫就會從中繼日誌中獲取數據並執行gtid的事務,並記錄到binlog中。 同一個事務在每臺數據庫服務器上所在的binlog名字和位置點可能都不同,自從有了gtid感受生活幸福的不要不要滴!!!由於同一個事務的gtid在全部節點上的值都是一致的。 GTID複製優勢: 根據gtid號能夠知道事務最初是在哪一個數據庫上提交的。 gtid的存在方便了主從複製的宕機切換(failover)。 GTID複製缺點: gtid實例和非gtid實例之間不能進行復制,也就是不能混用,要麼都是gtid,要麼都不是。 在同一事務中更新事務表與非事務表將致使多個gtid分配給同一事務。 MySQL GTID主從複製應用實踐 ---------------------------------------------------------------- 主機規劃 ---------------------------------------------------------------- 數據庫角色 主機名 bond0(SSH鏈接IP) bond1(內網通訊IP) ---------------------------------------------------------------- 主庫1(master) db01 10.0.0.11 192.168.10.11 ---------------------------------------------------------------- 主庫2(slave) db02 10.0.0.12 192.168.10.12 ---------------------------------------------------------------- 主庫my.cnf配置文件 [root@db01 ~]# cat /data/mysql/3306/my.cnf [mysqld] # for mysql global user = mysql basedir = /usr/local/mysql datadir = /data/mysql/3306/data tmpdir = /data/mysql/3306/tmp pid_file = /data/mysql/3306/3306.pid socket = /data/mysql/3306/mysql.sock port = 3306 server_id = 113306 character-set-server = utf8 # for binlog binlog_format = row log_bin = /data/mysql/3306/logs/mysql-bin # for error log log_error = /data/mysql/3306/error.log # general log general_log = off general_log_file = /data/mysql/3306/general.log # for slow query log slow_query_log = on slow_query_log_file = /data/mysql/3306/slow.log long_query_time = 1.000000 # for gtid gtid_mode = on enforce_gtid_consistency = on # for replication # for innodb [mysql] character-set-client = utf8 #prompt ="\\u@\\h [\\d]> \" #prompt ="mysql [\\d]> \" #prompt ="Master [\\d]> \" #prompt ="Slave [\\d]> \" [root@db01 ~]# vim /etc/my.cnf [mysql] prompt ="Master [\\d]> \" 從庫配置my.cnf文件 [root@db02 ~]# cat /data/mysql/3306/my.cnf [mysqld] # for mysql global user = mysql basedir = /usr/local/mysql datadir = /data/mysql/3306/data tmpdir = /data/mysql/3306/tmp pid_file = /data/mysql/3306/3306.pid socket = /data/mysql/3306/mysql.sock port = 3306 server_id = 123306 character-set-server = utf8 # for binlog binlog_format = row log_bin = /data/mysql/3306/logs/mysql-bin log_slave_updates = on # for error log log_error = /data/mysql/3306/error.log # general log general_log = off general_log_file = /data/mysql/3306/general.log # for slow query log slow_query_log = on slow_query_log_file = /data/mysql/3306/slow.log long_query_time = 1.000000 # for gtid gtid_mode = on enforce_gtid_consistency = on # for replication # for innodb [mysql] character-set-client = utf8 #prompt ="\u@\h [\d]> \" #prompt ="mysql [\d]> \" #prompt ="Master [\d]> \" #prompt ="Slave [\d]> \" [root@db02 ~]# vim /etc/my.cnf [mysql] prompt ="Slave [\d]> \" 啓動主庫實例 [root@db01 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf & 建立主從複製帳號 [root@db01 ~]# mysql -S /data/mysql/3306/mysql.sock -p Enter password: Master [(none)]> grant replication slave on *.* to 'rep'@'192.168.10.%' identified by '123'; Query OK, 0 rows affected, 1 warning (0.00 sec) Master [(none)]> flush privileges; Query OK, 0 rows affected (0.01 sec) Master [(none)]> reset master; Query OK, 0 rows affected (0.02 sec) Master [(none)]> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 154 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) Master [(none)]> exit; Bye 主庫進行全備 [root@db01 ~]# mysqldump -S /data/mysql/3306/mysql.sock -p -A -B -x --set-gtid-purged=off|gzip >/backup/db01_3306_$(date +%F).sql.gz Enter password: [root@db01 ~]# ls -lh /backup/ total 200K drwxr-xr-x 2 root root 29 Jul 12 03:50 conf -rw-r--r-- 1 root root 193K Jul 20 21:14 db01_3306_2019-07-20.sql.gz -rw-r--r-- 1 root root 2.2K Jul 15 05:28 eth0123.zip drwxr-xr-x 2 root root 54 Jul 12 05:39 sh drwxr-xr-x 2 root root 49 Jul 12 03:52 sql 將主庫全備傳到從庫 [root@db01 ~]# scp -rp /backup/db01_3306_$(date +%F).sql.gz root@192.168.10.12:/backup The authenticity of host '192.168.10.12 (192.168.10.12)' can't be established. ECDSA key fingerprint is SHA256:auBeaQTHqMvqa5fgR9w9UDEho26UWpxRqc0bHUwCv/Y. ECDSA key fingerprint is MD5:fc:ad:3a:4d:d7:83:20:a5:a1:49:c6:59:39:0b:1c:e5. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.10.12' (ECDSA) to the list of known hosts. root@192.168.10.12's password: db01_3306_2019-07-20.sql.gz 100% 192KB 13.4MB/s 00:00 將主庫全備恢復到從庫 [root@db02 ~]# mysqld --defaults-file=/data/mysql/3306/my.cnf & [root@db02 ~]# cd /backup/ [root@db02 /backup]# gzip -d db01_3306_2019-07-20.sql.gz [root@db02 /backup]# ls -l total 780 drwxr-xr-x 2 root root 29 Jul 12 03:50 conf -rw-r--r-- 1 root root 792654 Jul 20 21:14 db01_3306_2019-07-20.sql -rw-r--r-- 1 root root 2243 Jul 15 05:45 eth0123.zip drwxr-xr-x 2 root root 54 Jul 12 05:39 sh drwxr-xr-x 2 root root 49 Jul 12 03:52 sql [root@db02 /backup]# mysql -S /data/mysql/3306/mysql.sock -p < db01_3306_2019-07-20.sql Enter password: 登陸從庫配置複製參數 [root@db02 /backup]# mysql -S /data/mysql/3306/mysql.sock -p Enter password: change master to master_host='192.168.10.11', master_port=3306, master_user='rep', master_password='123', master_auto_position=1; Slave [(none)]> change master to -> master_host='192.168.10.11', -> master_port=3306, -> master_user='rep', -> master_password='123', -> master_auto_position=1; Query OK, 0 rows affected, 2 warnings (0.01 sec) Slave [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Master_Host: 192.168.10.11 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: Read_Master_Log_Pos: 4 Relay_Log_File: db02-relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 0 Relay_Log_Space: 154 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0 Master_UUID: Master_Info_File: /data/mysql/3306/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: ab0bfc5a-a681-11e9-bf5d-000c296165a9:1-123 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec) 從庫啓動複製 Slave [(none)]> start slave; Query OK, 0 rows affected (0.01 sec) Slave [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.10.11 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 434 Relay_Log_File: db02-relay-bin.000002 Relay_Log_Pos: 647 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 434 Relay_Log_Space: 853 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 113306 Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7 Master_Info_File: /data/mysql/3306/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-2 Executed_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-2, ab0bfc5a-a681-11e9-bf5d-000c296165a9:1-123 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec) [root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show slave status\G"|egrep "Running|Seconds" Enter password: Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates 測試主從複製 [root@db01 ~]# mysql -S /data/mysql/3306/mysql.sock -p Enter password: Master [(none)]> show master status; +------------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+------------------------------------------+ | mysql-bin.000001 | 434 | | | 7c145945-a680-11e9-baea-000c29a14cf7:1-2 | +------------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec) Master [(none)]> create database app01; Query OK, 1 row affected (0.00 sec) Master [(none)]> show master status; +------------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+------------------------------------------+ | mysql-bin.000001 | 596 | | | 7c145945-a680-11e9-baea-000c29a14cf7:1-3 | +------------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec) 查看從庫端複製狀況 Slave [(none)]> show master status; +------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+ | mysql-bin.000006 | 775111 | | | 7c145945-a680-11e9-baea-000c29a14cf7:1-3, ab0bfc5a-a681-11e9-bf5d-000c296165a9:1-123 | +------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) Slave [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | app01 | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.01 sec) gtid如何跳過事務衝突 傳統複製跳過事務作法:set global sql_slave_skip_counter = 1; gtid模式採用注入空事務的方法,來跳過事務衝突: stop slave; set gtid_next='xxx:n'; begin;commit; set gtid_next='aotumatic'; start slave; 測試案例: Slave [(none)]> create database app02; Query OK, 1 row affected (0.01 sec) Slave [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | app01 | | app02 | | mysql | | performance_schema | | sys | +--------------------+ 6 rows in set (0.00 sec) Slave [(none)]> show master status; +------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+ | mysql-bin.000006 | 775273 | | | 7c145945-a680-11e9-baea-000c29a14cf7:1-3, ab0bfc5a-a681-11e9-bf5d-000c296165a9:1-124 | +------------------+----------+--------------+------------------+--------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) Master [(none)]> create database app02; Query OK, 1 row affected (0.01 sec) Master [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | app01 | | app02 | | mysql | | performance_schema | | sys | +--------------------+ 6 rows in set (0.00 sec) Master [(none)]> show master status; +------------------+----------+--------------+------------------+------------------------------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+------------------------------------------+ | mysql-bin.000001 | 758 | | | 7c145945-a680-11e9-baea-000c29a14cf7:1-4 | +------------------+----------+--------------+------------------+------------------------------------------+ 1 row in set (0.00 sec) 從庫已經出了問題 Slave [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.10.11 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 758 Relay_Log_File: db02-relay-bin.000002 Relay_Log_Pos: 809 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1007 Last_Error: Error 'Can't create database 'app02'; database exists' on query. Default database: 'app02'. Query: 'create database app02' Skip_Counter: 0 Exec_Master_Log_Pos: 596 Relay_Log_Space: 1177 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 1007 Last_SQL_Error: Error 'Can't create database 'app02'; database exists' on query. Default database: 'app02'. Query: 'create database app02' Replicate_Ignore_Server_Ids: Master_Server_Id: 113306 Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7 Master_Info_File: /data/mysql/3306/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: 190720 21:45:26 Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-4 Executed_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-3, ab0bfc5a-a681-11e9-bf5d-000c296165a9:1-124 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec) 從庫故障解決 Slave [(none)]> stop slave; Query OK, 0 rows affected (0.01 sec) Slave [(none)]> set gtid_next='7c145945-a680-11e9-baea-000c29a14cf7:4'; Query OK, 0 rows affected (0.00 sec) 這是Retrieved_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-4裏的最大事務號 執行注入一個空事務 Slave [(none)]> begin;commit; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.01 sec) 自動比較gtid使複製繼續進行 Slave [(none)]> set gtid_next='automatic'; Query OK, 0 rows affected (0.00 sec) 開啓複製 Slave [(none)]> start slave; Query OK, 0 rows affected (0.01 sec) Slave [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.10.11 Master_User: rep Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 758 Relay_Log_File: db02-relay-bin.000003 Relay_Log_Pos: 454 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 758 Relay_Log_Space: 1477 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 113306 Master_UUID: 7c145945-a680-11e9-baea-000c29a14cf7 Master_Info_File: /data/mysql/3306/data/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-4 Executed_Gtid_Set: 7c145945-a680-11e9-baea-000c29a14cf7:1-4, ab0bfc5a-a681-11e9-bf5d-000c296165a9:1-124 Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: 1 row in set (0.00 sec) Slave [(none)]> exit; Bye [root@db02 ~]# mysql -S /data/mysql/3306/mysql.sock -p -e "show slave status\G"|egrep "Running|Seconds" Enter password: Slave_IO_Running: Yes Slave_SQL_Running: Yes Seconds_Behind_Master: 0 Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates