MySQL-主從複製

1、MySQL複製介紹

1.一、主從複製簡介

1)MySQL複製容許將主實例(master)上的數據同步到一個或多個從實例(slave)上,默認狀況下複製是異步進行的,從庫也不須要一直鏈接到主庫來同步數據html

2)MySQL複製的數據粒度能夠是主實例上全部的數據庫,也能夠是指定的一個或多個數據庫,也能夠是一個數據庫裏的指定的表mysql

1.二、主從複製優點

1)擴展能力:經過複製功能能夠將MySQL的性能壓力分擔到一個或多個slave上。這要求全部的寫操做和修改操做都必須在Master上完成,而讀操做能夠被分配到一個或多個slave上。將讀寫分離到不一樣服務器執行以後,MySQL的讀寫性能獲得提高sql

2)數據庫備份:因爲從實例是同步主實例的數據,因此能夠將備份做業部署到從庫shell

3)數據分析和報表:一樣,一些數據分析和報表的實現能夠在從實例執行,以減小對主庫的性能影響數據庫

4)容災能力:能夠在物理距離較遠的另外一個數據中心創建一個slave,保證在主實例所在地區遭遇災難時,在另外一個數據中心能快速恢復vim

1.三、MySQL複製方法

1)傳統方式:基於主庫的bin-log將日誌事件和事件位置複製到從庫,從庫再加以應用來達到主從同步的目的緩存

2)Gtid方式:global transaction identifiers是基於事務來複制數據,所以也就不依賴日誌文件,同時又能更好的保證主從庫數據一致性安全

1.四、MySQL複製類型

1)異步複製:一個主庫,一個或多個從庫,數據異步同步到從庫bash

2)同步複製:在MySQL Cluster中特有的複製方式服務器

3)半同步複製:在異步複製的基礎上,確保任何一個主庫上的事務在提交以前至少有一個從庫已經收到該事務並日志記錄下來

4)延遲複製:在異步複製的基礎上,人爲設定主庫和從庫的數據同步延遲時間,即保證數據延遲至少是這個參數

1.五、複製的原理

複製的工做原理是數據庫修改事件記錄到bin log中並傳遞到slave,而後slave在本地還原的過程。而事件記錄到bin log的格式會有所不一樣。

主從複製原理

1.六、複製的格式

1)基於語句的複製(statement based replication):基於主庫將SQL語句寫入到bin log中完成複製

2)基於行數據的複製(row based replication):基於主庫將每個行數據變化的信息做爲事件寫入到bin log中完成日誌

3)混合複製(mixed based replication):上述二者的結合。默認狀況下優先使用基於語句的複製,只有當部分語句若是基於語句複製不安全的狀況下才會自動切換爲基於行數據的複製

2、MySQL傳統複製:基於binlog的複製

2.一、簡介

1)基於binary log的複製是指主庫將修改操做寫入到bin log中,從庫負責讀取主庫的bin log,並在本地複製一份,而後將裏面的操做在從庫執行一遍

2)每一個從庫會保存目前讀取主庫日誌的文件名和日誌位置

3)主庫和每一個從庫都必須有一個惟一ID,叫server-id配置在配置文件中

2.二、主從複製前提

1)兩臺以上mysql實例

2)主庫開啓二進制日誌

3)專用的複製用戶

4)保證主從開啓以前的某個時間點,從庫數據是和主庫一致(主庫全備導入到從庫)

5)告知從庫,複製用戶信息,IP port,以及複製起點(change master to)

6)線程(三個):

  • master線程:Dump thread
  • slave線程: IO thread ,SQL thread   -->開啓(start slave)

2.二、傳統複製原理

aa

文字說明:

1. Slave 節點,經過IO線程,讀取master.info 的信息(IP port user,passwd,file+position )
2. IO Thread 經過鏈接信息,鏈接上主庫,主庫會生成DUMP THREAD
3. IO 經過 master.info 提供的 file+position,找主庫請求比這個新的二進制日誌事件 
4. Master  DUMP thread 截取全新的二進制日誌"事件",按照事件爲單元,串行傳送給 SLAVE IO THREAD
5. SLAVE IO THREAD收到發過來的二進制日誌事件,緩存到 TCP/IP cache中,當即返回ACK 給MASTER.
6. SLAVE  IO線程,更新master.info中二進制日誌信息(已經獲取過的二進制日誌信息),而且會將TCP/IP緩存
數據寫入relay-log日誌中
7. SLAVE SQL 線程,讀取relay-log.info ,獲取到上次已經執行過的relaylog 位置號
8. SQL 線程根據relaylog歷史記錄,日後繼續(串行)執行relaylog,執行完成後,再次更新relay-log.info信息
9. relay-log被應用完成後,會定時自動清理

2.三、配置過程

1)主庫須要開啓bin-log,而且指定一個惟一的server-id,重啓數據庫

[mysqld]
datadir = /data/data
log-bin = mysql-bin
server-id = 1

#在同一個複製組下的全部實例的server_id都必須是惟一的,並且取值必須是正整數,取值範圍是1~(232)−1 確保主庫的my.cnf中skip-networking參數爲非開啓狀態,不然會致使主從庫不能通訊而複製失敗

[root@master ~]# /etc/init.d/mysql.server start
[root@master ~]# mysql -uroot -pmysql
mysql> show variables like '%log_bin%';
+---------------------------------+----------------------------+
| Variable_name                   | Value                      |
+---------------------------------+----------------------------+
| log_bin                         | ON                         |
| log_bin_basename                | /data/data/mysql-bin       |
| log_bin_index                   | /data/data/mysql-bin.index |
| log_bin_trust_function_creators | OFF                        |
| log_bin_use_v1_row_events       | OFF                        |
| sql_log_bin                     | ON                         |
+---------------------------------+----------------------------+
[root@master data]# ls mysql-bin.*
mysql-bin.000001  mysql-bin.index

2)在主庫建立一個專門用來作複製的數據庫用戶,這樣全部從庫均可以用這個用戶來鏈接主庫,也能夠確保這個用戶只有複製的權限。雖然能夠用任何擁有複製權限的MySQL用戶來創建複製關係,但因爲被使用的用戶名和密碼會明文保存在備庫的master.info文件中,因此爲安全起見,最好是使用僅有複製權限的獨立用戶

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

3)從slave庫驗證遠程鏈接主庫是否正常

[root@slave ~]# mysql -urepl -pmysql -P 3306 -h 10.0.0.51

4)獲取主庫的日誌信息

爲了確保創建的備庫能從正確的bin log位置開啓複製,要首先獲取主庫的bin log信息,包括當前的日誌文件名和日誌文件內的位置

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------------------------------------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                   |
+------------------+----------+--------------+------------------+-------------------------------------------------------------------------------------+
| mysql-bin.000001 |      770 |              |                  | 3413f1ef-ee30-11e8-aeb5-000c29e5974b:1-18,
36dbc733-f24d-11e8-8988-000c2966cef5:1-3 |
+------------------+----------+--------------+------------------+-------------------------------------------------------------------------------------+

---------------------------------------------------------------
#當加鎖後
mysql> drop table temp; 
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock 
mysql> create database temp2; 
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock 
mysql> insert into temp values(now()); 
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock

5)主庫數據生成鏡像並上傳到從庫

兩種方式生成鏡像

  1. mysqldump,是innodb存儲引擎推薦的方式;
  2. 數據文件從主庫拷貝到從庫,這種方式效率更高(省去了dump/import過程當中insert語句執行致使的更新index的行爲),但innodb不推薦使用

①、使用mysqldump方式

[root@master ~]# mysqldump --all-databases --master-data -u root -pmysql -P 3306 > dbdump.db 
[root@master ~]# scp -rp dbdump.db root@10.0.0.52:~
mysql> unlock tables;  #主庫釋放鎖

#mysqldump方式導出全部數據庫數據到dbdump.db文件,
#--master-data表示導出數據直接加上change master to參數以便備庫使用
---------------------------------------------------------------------------------

[root@db01 data]# mysqldump -S /data/3307/mysql.sock -A --master-data=2 -R --triggers --single-transaction >/backup/full.sql
[root@db01 data]# vim /backup/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=775;

②、數據文件拷貝(須要停主庫)

須要將主庫臨時關閉,並將數據文件(data目錄)拷貝到從庫上

6)從庫配置惟一server-id,並重啓mysql實例,從庫的bin log屬性能夠打開也能夠不打開

[mysqld]
server-id=2

7)從庫應用主庫的數據鏡像

Mysqldump的鏡像,經過source命令執行,若時原始數據文件拷貝的鏡像,將文件複製到和主庫相同的目錄下

mysql> source /root/dbdump.db;

8)從庫指定主庫的日誌信息和連接信息

CHANGE MASTER TO MASTER_HOST='10.0.0.51', 
MASTER_PORT=3306, 
MASTER_USER='repl', 
MASTER_PASSWORD='mysql', 
MASTER_LOG_FILE='mysql-bin.000001', 
MASTER_LOG_POS=770;
----------------------------------------------

CHANGE MASTER TO
  MASTER_HOST='master2.mycompany.com',  #主庫的主機名
  MASTER_USER='replication',			#複製的數據庫用戶名
  MASTER_PASSWORD='bigs3cret',			#複製的數據庫用戶密碼
  MASTER_PORT=3306,						#主庫的端口
  MASTER_LOG_FILE='master2-bin.001',	#主庫的日誌文件名
  MASTER_LOG_POS=4,						#主庫的日誌文件位置
  MASTER_CONNECT_RETRY=10;				#主庫鏈接重試次數

9)從庫啓動複製進程並查看狀態

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.51
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 770
               Relay_Log_File: slave-relay-bin.000002
                Relay_Log_Pos: 320
        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: 770
              Relay_Log_Space: 527
              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: 1
                  Master_UUID: 5874e7c6-e753-11e9-91e7-000c29db13e4
             Master_Info_File: /data/mysql/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: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version:

10) 驗證複製工做正常:基本方法是在主庫添加任意數據,查看從庫是否能查詢到

11)查看主從線程

#主庫上執行
mysql> show processlist;
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User | Host            | db   | Command     | Time | State                                                         | Info             |
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
|  7 | root | localhost       | NULL | Query       |    0 | starting                                                      | show processlist |
|  8 | repl | 10.0.0.52:50994 | NULL | Binlog Dump | 1227 | Master has sent all binlog to slave; waiting for more updates | NULL             |
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+

#從庫上執行
mysql> show processlist;
+----+-------------+-----------+-------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db    | Command | Time | State                                                  | Info             |
+----+-------------+-----------+-------+---------+------+--------------------------------------------------------+------------------+
|  3 | root        | localhost | world | Query   |    0 | starting                                               | show processlist |
|  4 | system user |           | NULL  | Connect | 1244 | Waiting for master to send event                       | NULL             |
|  5 | system user |           | NULL  | Connect |  473 | Slave has read all relay log; waiting for more updates | NULL             |
+----+-------------+-----------+-------+---------+------+--------------------------------------------------------+------------------+

2.四、常見錯誤及修復

2.4.一、錯誤一

Last_IO_Errno: 1593
Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
解決辦法:刪除備庫的auto.cnf文件,重啓mysql,生成新的UUID

2.4.二、錯誤二

Last_IO_Errno: 2003
Last_IO_Error: error connecting to master 'repl@10.0.0.51:3306' - retry-time: 60 retries: 19
#解決辦法:備庫鏈接主庫失敗,檢查防火牆,用戶密碼端口是否設置正確

2.4.三、錯誤三

#複製過程當中因爲備份以前沒有lock全表而致使的數據複製異常
#主庫上執行:
Delimiter //
Create procedure proc1()
Begin
	Declare n int default 1;
	while n<=20000 do
		Insert into temp values(n, 'mike');
		Set n=n+1;
	End while;
End;
//
delimiter ;
mysql> show master status;
mysql> call proc1();
存儲過程執行過程當中開始mysqldump,並創建從庫

2.4.四、IO線程故障

1)鏈接主庫的用戶,密碼,IP,port錯誤

Last_IO_Errno: 1045
Last_IO_Error: error connecting to master 'repl@10.0.0.51:3307' - retry-time: 10  retries: 2

#解決方法:手動登陸複製用戶,看是否能鏈接
[root@db01 data]# mysql -urepl -p123456 -h 10.0.0.51 -P 3307		#密碼實際上是錯誤的
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'repl'@'db01' (using password: YES)
鏈接不上說明相關信息錯誤
處理方法:
		stop  slave  
		reset slave all 
		change master to 	#填寫正確的信息
		start slave

#反向解析問題解決:在配置文件中添加skip_name_resolve並重啓
[root@db01 data]# vim /data/3307/my.cnf
[mysqld]
skip_name_resolve

2)主庫鏈接數已經達到上限(或主庫太繁忙)

#報錯:
Last_IO_Errno: 1040		#與上面的報錯信息相同,但報錯代碼不同
Last_IO_Error: error reconnecting to master 'repl@10.0.0.51:3307' - retry-time: 10  retries: 7

#實驗模擬:
mysql> show variables like '%max_connections%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 151   |		#最大鏈接數
+-----------------+-------+
1 row in set (0.01 sec)

#將最大鏈接數調小測試
mysql> set global max_connections=3;	#其實能夠鏈接的最大鏈接數是4個
#同時開多個mysql鏈接(4個),再次使用複製用戶鏈接
[root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P 3307 
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1040 (HY000): Too many connections
解決方法:調大最大鏈接數的大小
mysql> set global max_connections=300;

3)防火牆阻擋,網絡不通

4)從庫請求不到二進制日誌(主庫缺乏日誌) #嚴令禁止主庫中reset master;

#當在主庫上執行reset master命令,會清空binlog日誌,報錯以下:
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the first event 'mysql-bin.000002' at 154, the last event read from '/data/3307/data/mysql-bin.000002' at 123, the last byte read from '/data/3307/data/mysql-bin.000002' at 154.'

#解決方法:從新構建主從
stop  slave  
reset slave all 
change master to 
start slave

#注意:在主從複製環境中,嚴令禁止主庫中reset master; 能夠選擇expire進行按期清理主庫二進制日誌
mysql> show variables like '%expire%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| disconnect_on_expired_password | ON    |
| expire_logs_days               | 0     |	#通常設置爲全備日期加1天
+--------------------------------+-------+

5)從庫change master to位置點不對

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'binlog truncated in the middle of event; consider out of disk space on master; the first event 'mysql-bin.000001' at 158, the last event read from '/data/3307/data/mysql-bin.000001' at 123, the last byte read from '/data/3307/data/mysql-bin.000001' at 201.' 
#解決方法:在master上找到位置點,從新在從庫上執行change master to

2.4.五、SQL線程故障

故障緣由:

1)讀寫relay-log.info故障(不多)
2)relay-log損壞,斷節,找不到(不多)
3)接受的SQL沒法執行
	一、SQL_MODE影響
	二、要建立的數據庫對象,已經存在
	三、要刪除或修改的對象不存在	
	四、DML語句不符合表定義及約束時.

#歸根揭底的緣由都是因爲從庫發生了寫入操做

故障模擬:

#故障模擬:
1.構建正確的主從關係
2.在從庫上建庫測試
mysql> create database test;
3.在主庫建立test庫,此時會同步從庫
mysql> create database test;
4.查看從庫狀態(報錯)
mysql> show slave status\G
Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can't create database 'test'; database exists' on query. Default database: 'test'. Query: 'create database test'

#解決方法:
一、以從庫爲核心的處理方案:同步指針向下移動(能夠執行屢次)
stop slave; 
set global sql_slave_skip_counter = 1;
start slave;

#能夠編輯配置文件,跳過錯誤(有風險,最安全的方法是從新構建主從)
/etc/my.cnf
slave-skip-errors = 1032,1062,1007		#跳過指定的錯誤

常見的錯誤代碼:
1007:對象已存在
1032:沒法執行DML
1062:主鍵衝突,或約束衝突

二、設置從庫只讀,添加中間件實現讀寫分離
mysql> show variables like '%read_only%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | OFF   |		#對超級管理員有效
| read_only             | OFF   |		#只對普通用戶有效
| super_read_only       | OFF   |		#對超級管理員有效
| transaction_read_only | OFF   |
| tx_read_only          | OFF   |
+-----------------------+-------+

2.4.六、主從延時故障

#從庫延時較長緣由:
一、主庫寫binlog不及時
控制binlog從內存寫入磁盤的控制開關sync_binlog
sync_binlog=1	#每次事務提交都當即刷新binlog到磁盤(雙一標準中的其一)
sync_binlog=0	#每次事務提交不當即寫入磁盤,靠操做系統判斷何時寫入

二、dump線程致使,系統資源壓力大
從庫越多,dump線程壓力越大
解決方法:
	1)減小頻繁小事務,減小超大事務  
	2)group commit
三、IO線程阻塞
大事務拆成小事務
事務量大(主庫壓力大)
	1) group commit能夠緩解
	2) 業務的分離和分佈式(Mycat,InnoDB Cluster)

四、SQL線程慢
從庫 默認只有一個SQL線程,從庫中的事務都是一個一個串行來執行的,主庫能夠並行多個事務,但會形成從庫延時

#傳統複製 主從延時緣由小結
1. 主庫binlog日誌寫入不及時
2. dump繁忙 (串行傳送日誌)
3. IO線程阻塞(主庫大事務,頻繁事務,串行接收日誌)
4. SQL線程 (串行的執行事務)

#解決方案:
group commit(DUMP和IO)  
多線程複製(SQL多線程)

#如何監控主從延時:
show slave status \G
(1) Seconds_Behind_Master		#從庫延時秒數
(2) 對比從庫中master.info和relay.info, show relaylog events in 'db01-relay-bin.000006';
監控延時的日誌量
(3)pt-heartbeat

2.4.七、主從重點關注

#線程相關監控  
#主庫: 
show full processlist;
#每一個從庫都會有一行dump相關的信息
HOSTS: 
db01:47176
State:
Master has sent all binlog to slave; waiting for more updates
#若是現實非以上信息,說明主從之間的關係出現了問題
		
#從庫:
show slave status \G;
db01 [(none)]>show slave status \G
*************************** 1. row ***************************

#主庫有關的信息(master.info):重點關注
Master_Host: 10.0.0.51
Master_User: repl
Master_Port: 3307
Connect_Retry: 10
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 444
		  
#從庫relaylog的信息(已經執行過的relaylog的位置點):重點關注
Relay_Log_File: db01-relay-bin.000002
Relay_Log_Pos: 320


#從庫 兩個線程的基本狀態:(重點關注)
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#說明:在正常的主從複製關係中,都是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

#從庫和主庫延時的秒數:
Seconds_Behind_Master: 0

#分別記錄的IO和SQL報錯的具體信息(重點關注)
Last_IO_Errno: 0
Last_IO_Error: 
Last_SQL_Errno: 0
Last_SQL_Error: 

#延時從庫的狀態
SQL_Delay: 0
SQL_Remaining_Delay: NULL


#GTID複製有關的狀態
Retrieved_Gtid_Set: 
Executed_Gtid_Set: 
Auto_Position: 0

2.五、拓展slave數量

1)當第一個slave建立好以後,若是還想建立其餘的slave,則能夠直接使用先前使用的備份文件,分別執行:

  • a)在slave的my.cnf上分配新的server_id
  • b)從庫應用主庫的數據鏡像
  • a)利用相同的change master命令將從庫指定主庫的日誌信息和連接信息
  • c)Slave start

2)若是想在過後再增長一個slave,但以前的備份文件已經不存在,或者主庫的日誌文件已經被清除了的狀況下,考慮使用以下辦法: 在已經創建好的複製環境中新增一個從庫,則不須要關閉主庫複製數據,而是用已有的從庫複製數據便可

  • a)關閉現有的從庫
  • mysqladmin shutdown
  • b)拷貝從庫的文件到新的從庫,包括log文件和relay log文件,其中若是relay log使用了從庫的主機名,則須要調relay-log-index參數
  • c)爲新的從庫分配一個惟一的server-id,注意須要刪除auto.cnf
  • d)新的從庫啓動slave進程

2.六、複製相關係統變量

1)server_id

是必須設置在master和每一個slave上的惟一標識ID,其取值範圍是1~4294967295之間,且同一個複製組以內不能重複

2)server_uuid

server_uuid會在GTID複製中使用。當MySQL啓動以後,會首先到數據文件目錄下的auto.cnf中尋找是否有指定的server_uuid,若是沒有找到,則本身生成一個server_uuid並保存到這個文件中

3)log_slave_updates

該參數用來控制是否將收到的主庫的更新數據的語句也記錄在slave本身的bin log中。正常狀況下是不須要記錄的,但若是是想建立級聯複製關係,好比A -> B -> C,這其中B既要做爲A的從庫,也要做爲C的主庫,則須要既開啓log-bin參數,也要開啓log_slave_updates參數

4)relay-log

該參數用來指定relay-log文件的基礎名稱,默認的名稱爲host_name-relay-bin.xxxx,其中的xxxx結尾是依次遞增的數字

5)replicate-do-db

該參數用來指定須要複製的數據庫。

①在基於語句statement複製的環境中,指定該參數以後,則slave的SQLthread進程只會應用在本數據庫下的對象相關的語句。若是有多個數據庫須要複製,則這個參數要使用屢次。但若是是涉及到跨庫操做語句,則複製會丟失,好比:

#my.cnf配置
replicate-do-db=sales 

#sql執行語句
USE prices; UPDATE sales.january SET amount=amount+1000; 

②在基於行row複製的環境中,只要數據庫對象是指定的庫,則複製都能正常,好比上述update語句因爲january表是屬於sales庫的,則slave會複製並應用,一樣下面的語句在基於行復制的環境中也不會執行:

USE sales; UPDATE prices.march SET amount=amount-25; #不會執行
#在slave的my.cnf上設置replicate-do-db=test,重啓mysql
#查看從庫的狀態信息:
mysql> show slave status\G;
*************************** 1. row ***************************
 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes
 Replicate_Do_DB: test
 
#在主庫上執行:
mysql> use test;
mysql> insert into temp values(5,'e');
mysql> use test2;
mysql> insert into temp values(13,'dd');

#在備庫上查看複製狀況:
mysql> use test;
mysql> select * from temp; ##數據有複製
+------+------+
| id   | name |
+------+------+
| 1    |   a  |
| 2    |   b  |
| 3    |   c  |
| 4    |   d  |
| 5    |   e  |
+------+------+

mysql> use test2;
mysql> select * from temp; ##數據沒有複製
----------------------------------------------------

#在語句statement複製環境下查看對指定數據庫的修改操做:
[mysqld]
binlog-format=statement

#主庫上執行:
mysql> use test;
mysql> update test2.temp set name='ddd';
mysql> use test2;
mysql> update test.temp set name='eee';

#在從庫上查看複製結果:
mysql> use test;
mysql> select * from temp; ##雖然是指定的同步數據庫但並無同步
+------+------+
| id | name |
+------+------+
| 1 | abc |
| 2 | abc |
| 3 | abc |
| 4 | abc |
| 5 | abc |
+------+------+
mysql> use test2;
mysql> select * from temp; ##雖然不是指定的同步數據庫但數據有同步
+------+------+
| id | name |
+------+------+
| 10 | ddd |
| 11 | ddd |
| 12 | ddd |

------------------------------------------------------------
#在行復制環境下查看對指定數據庫的修改操做:
mysql> show variables like '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+

#主庫上執行:
mysql> use test;
mysql> update test2.temp set name='bcd';
mysql> use test2;
mysql> update test.temp set name='abc';

#在從庫上查看複製結果:
mysql> use test;
mysql> select * from temp; ##數據已複製
+------+------+
| id | name |
+------+------+
| 1 | abc |
| 2 | abc |
| 3 | abc |
| 4 | abc |
| 5 | abc |
+------+------+
mysql> use test2;
mysql> select * from temp; ##數據未複製
+------+------+
| id | name |
+------+------+
| 10 | aa |
| 11 | bb |
| 12 | cc |
+------+------+

另外一個基於SQL語句複製和基於行復制的區別在於當語句中包含對多個數據庫的表進行操做時。
好比設置
replicate-do-db=db1, 
USE db1; UPDATE db1.table1 SET col1 = 10, db2.table2 SET col2 = 20; 
基於SQL語句的複製會將table1和table2都在備庫修改,
而基於行的複製只會在備庫修改table1表 
USE db4; UPDATE db1.table1 SET col1 = 10, db2.table2 SET col2 = 20; 
而對於上述語句來講,基於SQL語句的複製不會在備庫修改任何表,而基於行的複製會在備庫修改table1表 若是但願跨庫的update語句在多個庫上都起做用,可使用replicate-do-table=db_name.tbl_name

6)replicate-ignore-db

該參數決定了忽略指定數據庫的複製,其行爲和replicate-do-db正好相反

7)replicate-do-table=db_name.tbl_name

經過該參數告知slave的SQL thread僅複製指定表上的數據。若是有多個表,則該參數要使用屢次

image

8)replicate-ignore-table=db_name.tbl_name

經過該參數告知slave的SQL thread將指定表上的數據過濾掉

9)replicate-wild-do-table=db_name.tbl_name

經過該參數告知SQL的SQL thread僅複製符合匹配的表,可使用_和%做爲通配符。好比replicate-wild-do-table=foo%.bar%表示複製以foo打頭的數據庫下全部bar打頭的表數據。若是是replicate-wild-do-table=foo%.%,則表示即複製foo打頭的全部表的數據,也複製create/drop/alter database foo打頭的命令

10)replicate-wild-ignore-table=db_name.tbl_name

經過該參數告知SQL的SQL thread過濾掉符合匹配的表

11)slave-parallel-workers

該參數決定了slave上啓動多個SQL thread線程來並行應用數據的。默認值是0表明不容許並行,取值範圍能夠是0~1024

[mysqld] 
slave-parallel-workers=5

12)skip-slave-start

該參數決定了在MySQL啓動時是否先不啓動slave線程,即暫停複製

[mysqld] 
skip-slave-start=1

13)slave-parallel-type=type

該參數決定了當啓動了並行以後,採用什麼粒度的並行方式。默認值database表示按照不一樣的數據庫執行並行,LOGICAL_CLOCK則表示按照在binlog中的一組提交的事務做爲並行粒度

14)slave-skip-errors=[err_code1,err_code2,...|all|ddl_exist_errors]

該參數決定了當slave的SQLthread執行過程當中碰到何種錯誤時能夠忽略並繼續接下來的數據複製。正常狀況下當有錯誤發生時,複製會中止而須要人工干預修復才能繼續進行。除非很是自信能夠忽略某些錯誤,不然不要使用這個參數,否則會致使雖然複製執行正常,但其實內部的數據已經徹底不一致

15)sql_slave_skip_counter

表明在非GTID複製環境下,經過設置此參數來跳過多少個複製事件。設置完該參數並不是當即生效,而是要等待下次start slave命令的執行生效,並將該參數再次設置爲0

16)log-bin[=base_name]

該參數表示是否開啓binary log。默認狀況下MySQL會使用host_name-bin.xxxx做爲文件的名字,其中xxxx是以數字遞增的後綴。若是該參數指定了base_name,則二進制文件會以base_name.xxxx來命名

17)binlog-do-db=db_name

該參數決定了哪些庫下的修改會被記錄到bin log中。其行爲與replicate-do-db類型,

一、在基於SQL語句複製的環境下,只記錄在當前數據庫下的修改。好比指定binlog-do-db=sales,如下語句不會被記錄到bin log中:
USE prices; UPDATE sales.january SET amount=amount+1000; 
而如下語句則會被記錄到bin log中:
USE sales; UPDATE prices.discounts SET percentage = percentage + 10; 

二、而基於行復制的環境下,只有屬於指定數據的語句纔會被記錄到bin log中。好比下面的語句 會被記錄: 
USE prices; UPDATE sales.february SET amount=amount+100; 
而下面的語句則不會被記錄: 
USE sales; UPDATE prices.march SET amount=amount-25; 

三、針對跨庫的語句來講,行爲和replicate-do-db相同

18)binlog-ignore-db=db_name

該參數決定了在bin log中忽略的數據庫,其行爲與replicate-ignore-db相似

19)binlog_format

該參數決定了bin log中記錄的格式,能夠是statement,row,mixed,分別表明基於SQL語句的複製,基於行復制和基於混合複製。在5.7.7版本以前的默認設置是statement,在5.7.7及之後,則默認是row。當設置爲混合模式時,則優先使用statement,只有當基於語句的複製沒法保證複製的準確時會自動替換爲row

2.七、檢查複製狀態方法

1)在slave上執行show slave status來檢查複製是否正常工做

Slave_IO_State:表明當前slave的狀態 
Slave_IO_Running:表明負責讀取主庫bin log的IO線程是不是運行狀態,正常狀況下應該是YES 
Slave_SQL_Running:表明負責執行備庫relay log的SQL線程是不是運行狀態,正常狀況下應該是YES 
Last_IO_Error, Last_SQL_Error: 分別表明最後一次IO線程和SQL線程所發生的錯誤,正常狀況下應該是空表明沒有錯誤 
Seconds_Behind_Master:表明備庫的SQL線程比主庫的bin log晚多少秒。0表明目前沒有複製延遲 
(Master_Log_file, Read_Master_Log_Pos):表示IO線程在主庫bin log中的座標位置 
(Relay_Master_Log_File, Exec_Master_Log_Pos):表示SQL線程在主庫bin log中的座標位置 
(Relay_Log_File, Relay_Log_Pos):表示SQL線程在備庫relay log中的座標位置

2)主庫能夠經過執行show processlist命令查看主庫的bin log日誌生成進程

mysql> show processlist;
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User | Host            | db   | Command     | Time | State                                                         | Info             |
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
|  7 | root | localhost       | NULL | Query       |    0 | starting                                                      | show processlist |
|  8 | repl | 10.0.0.52:50994 | NULL | Binlog Dump | 1227 | Master has sent all binlog to slave; waiting for more updates | NULL             |
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+

2.八、MySQL複製格式

image

2.九、MySQL複製線程

MySQL複製涉及三個線程,其中一個在主庫,另兩個在從庫

  • binlog dump thread:在主庫建立,用來在從庫連接過來時發送bin log的內容
  • slave io thread:在備庫建立,用來鏈接主庫並請求發送新的bin log內容。該線程讀取主庫的bin log dump線程發送的更新內容並將此內容複製到本地的relay log中
  • Slave sql thread:在備庫建立,讀取slave io線程在本地relay log中的內容並在本地執行內容中的事件
#主庫執行
mysql> show processlist;
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User | Host            | db   | Command     | Time | State                                                         | Info             |
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+
|  3 | repl | 10.0.0.52:48344 | NULL | Binlog Dump |  801 | Master has sent all binlog to slave; waiting for more updates | NULL             |
|  4 | root | localhost       | NULL | Query       |    0 | starting                                                      | show processlist |
+----+------+-----------------+------+-------------+------+---------------------------------------------------------------+------------------+

#從庫執行
mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time | State                                                  | Info             |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  1 | system user |           | NULL | Connect |  836 | Waiting for master to send event                       | NULL             |
|  2 | system user |           | NULL | Connect |  835 | Slave has read all relay log; waiting for more updates | NULL             |
|  6 | root        | localhost | NULL | Query   |    0 | starting                                               | show processlist |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+

複製啓停方法:

#在slave暫停複製的方法: 
#總體中止的方法:
mysql> STOP SLAVE; 
#中止指定線程的方法: 
mysql> STOP SLAVE IO_THREAD; 
mysql> STOP SLAVE SQL_THREAD; 

#總體開啓的方法:
mysql> START SLAVE; 
#開啓指定線程的方法: 
mysql> START SLAVE IO_THREAD; 
mysql> START SLAVE SQL_THREAD;

2.十、MySQL複製使用場景

1)MySQL複製能夠做爲數據庫備份的一種解決方案,因爲主庫的數據會複製到備庫,因此能夠在備庫執行數據庫備份做業而不用影響主庫的性能 在備庫的備份一般有兩種選擇:

①當數據庫比較小時,能夠採用mysqldump的方式。因爲mysqldump出來的文件內容是SQL語句,因此能夠很方便的將其中的一部分複製出來應用到其餘數據庫裏。在執行mysqldump以前,爲了保證數據的一致性,最好是把slave進程停掉。

shell> mysqladmin stop-slave
#或者
shell> mysql -e 'STOP SLAVE SQL_THREAD;' 

shell> mysqldump --all-databases > fulldb.dump 
shell> mysqladmin start-slave

②當數據庫比較大時,採用mysqldump方式的效率不高,因此可使用物理文件拷貝的方式。爲了保證數據的一致性,物理備份須要將備庫關閉

shell> mysqladmin shutdown 
shell> tar cf /tmp/dbbackup.tar ./data 
/etc/init.d/mysql.server start

2)MySQL複製能夠用在主庫和從庫採用不一樣的存儲引擎的狀況下。這樣作的目的一般是在主庫和從庫能夠分別利用不一樣存儲引擎的優點,好比在主庫使用InnoDB是爲了事務功能,而從庫使用MyISAM由於是隻讀操做而不須要事務功能

①當使用mysqldump方式來建立備庫時,改變備庫的表存儲引擎的方式就是在應用dump文件以前先修改文件裏的全部關於表存儲引擎的地方

②若是是使用文件拷貝的方式來建立備庫時,則惟一修改備庫表存儲引擎的方式就是在啓動備庫以後使用alter table命令修改

mysql> STOP SLAVE; 
執行ALTER TABLE ... ENGINE='engine_type'命令 
mysql> START SLAVE;

3)MySQL複製能夠用來作負載均衡功能的水平擴展,最主要是將數據庫的讀壓力分擔到多個MySQL slave實例上,這種狀況適用在讀多寫少的環境中。好比一個基本的WEB架構

image

4)MySQL複製能夠用在當須要將主庫上的不一樣數據庫複製到不一樣的slave上,以便在不一樣的slave上執行不一樣的數據分析任務時。 能夠在每一個slave上配置不一樣的參數來約束複製過來的數據,經過replicate-wild-do-table參數或者replicate-do-db參數

image

slave1上應該配置參數replicate-wild-do-table=databaseA.% 
slave2上應該配置參數replicate-wild-do-table=databaseB.% 
slave3上應該配置參數replicate-wild-do-table=databaseC.% 
每一個slave實際上是接收到完整的bin log日誌,但在應用環節中會進行過濾,僅應用符合參數配置的事件 在配置完參數以後,經過mysqldump的方式將對應數據庫在slave應用起來,再啓動slave線程

2.十一、延遲複製

2.11.一、延遲複製介紹

延遲複製是指定從庫對主庫的延遲至少是指定的這個間隔時間,默認是0秒。能夠經過change master to命令來指定 CHANGE MASTER TO MASTER_DELAY = N; 其原理是從庫收到主庫的bin log以後,不是當即執行,而是等待指定的秒數以後再執行

2.11.二、延遲複製的使用場景

1)確保在主庫上被錯誤修改的數據能及時找回

2)測試在從庫IO集中在恢復bin log過程當中對應用程序的訪問影響

3)保留一份若干天前的數據庫狀態,和當前狀態能夠作對比

4)show slave status中SQL_Delay值代表了設置的延遲時長

2.11.三、延遲複製配置

#在slave上執行
mysql> stop slave;
mysql> CHANGE MASTER TO MASTER_DELAY = 60;
mysql> start slave;

#在主庫上執行
mysql> insert into temp values(3,'cc');
mysql> insert into temp values(4,'dd');

#在slave上查看複製狀況
mysql> select * from temp;  #數據沒有同步過來
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    2 | bb   |
+------+------+

mysql> show slave status\G
          Exec_Master_Log_Pos: 784
        Seconds_Behind_Master: 36 
                    SQL_Delay: 60 #設置的主從延時秒數
          SQL_Remaining_Delay: 24  #延遲時間實時顯示
      Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event

#等待60s後數據同步過來了
mysql> select * from temp;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    2 | bb   |
|    3 | cc   |
|    4 | dd   |
+------+------+

mysql> show slave status\G
        Seconds_Behind_Master: 0
                    SQL_Delay: 60
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates

2.十二、MySQL複製主從切換

1)若是是使用GTID的複製方式,可使用mysqlfailover工具作主從複製狀態的監控和自動切換;

2)若是是使用非GTID模式,則須要使用其餘的方式作監控和切換 當新的master產生以後,須要經過在其餘slave上執行change master to語句來對應到新的master上。slave不會檢查本身的數據庫和新的master上是否一致,而是直接獲取master上的二進制日誌並繼續本身的複製功能

3)新當選master的實例須要運行在log_bin模式

image

4)配置方法

一、新的master上開啓log-bin=mysql-bin,Master上查看bin log信息 
mysql> show master status;

二、在slave上執行: 
mysql> reset slave all;
mysql> stop slave; 
CHANGE MASTER TO
 MASTER_HOST='192.168.237.130', #新的master
 MASTER_PORT=3308,
 MASTER_USER='repl',
 MASTER_PASSWORD='mysql',
 MASTER_LOG_FILE='mysql-bin.000001',
 MASTER_LOG_POS=154; 
 
mysql> start slave;

3、MySQL半同步複製

3.一、半同步複製介紹

1)默認建立的MySQL複製是異步的,意味着主庫將數據庫修改事件寫入到本身的bin log,而並不知道從庫是否獲取了這些事件並應用在本身身上。因此當主庫崩潰致使要主從切換時,有可能從庫上的數據不是最新的

2)從5.7版本開始MySQL經過擴展的方式支持了半同步複製 ,當主庫執行一個更新操做事務時,提交操做會被阻止直到至少有一個半同步的複製slave確認已經接收到本次更新操做,主庫的提交操做纔會繼續

3)半同步複製的slave發送確認消息只會在本次更新操做記錄已經記錄到本地的relay log以後,若是沒有任何slave發送確認消息而致使超時時,半同步複製會轉換成異步複製

4)半同步複製會對MySQL性能產生影響,由於主庫的提交動做只有在收到至少一個從庫的確認消息以後才能執行。但這個功能是性能和數據可靠性方面的權衡

3.二、半同步複製原理

半同步複製工做原理的變化
1. 主庫執行新的事務,commit時,更新 show master  status\G ,觸發一個信號給dump線程
2. dump線程接收到主庫的 show master status\G信息,通知從庫日誌更新了
3. 從庫IO線程請求新的二進制日誌事件
4. 主庫會經過dump線程傳送新的日誌事件,給從庫IO線程
5. 從庫IO線程接收到binlog日誌,當日志寫入到磁盤上的relaylog文件時,發送信號給主庫ACK_receiver線程
6. ACK_receiver線程觸發一個事件,告訴主庫commit能夠成功了
7. 若是ACK達到了咱們預設值的超時時間,半同步複製會切換爲原始的異步複製

3.二、半同步複製相關參數

1)rpl_semi_sync_master_wait_point參數用來控制半同步複製的行爲:

  • AFTER_SYNC:默認值
  • AFTER_COMMIT

2)須要配置的系統參數包括:

  • rpl_semi_sync_master_enabled:在主庫配置,確保主庫的半同步複製功能開啓
  • rpl_semi_sync_master_timeout:配置主庫等待多少毫秒時間來保證接收備庫的確認消息,當超過這個時間時,半同步變成異步方式
  • rpl_semi_sync_slave_enabled:在從庫配置,確保從庫的半同步複製功能開啓

3.三、半同步配置過程

半同步複製是經過插件的方式創建,要分別在主庫和從庫安裝一個插件 show plugins;

前提條件

  • 5.5版本及以上
  • have_dynamic_loading參數必須是YES表明能夠安裝插件並動態加載 mysql> show variables like '%have_dynamic_loading%';
  • 事先創建好異步複製關係

1)主庫安裝插件

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME          | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+

2)從庫上安裝插件

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+---------------------+---------------+
| PLUGIN_NAME         | PLUGIN_STATUS |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE        |
+---------------------+---------------+

3)在主庫上開啓半同步複製

mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
mysql> SET GLOBAL rpl_semi_sync_master_timeout = 60000; #N是毫秒,默認是10000,表明10秒 

4)在備庫上開啓半同步複製

mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;

5)在備庫上重啓slave進程

mysql> STOP SLAVE IO_THREAD; 
mysql> START SLAVE IO_THREAD;

6)查看狀態

mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+

3.四、半同步複製監控參數

mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';	#查看各個參數的狀態

#半同步複製監控參數: 
Rpl_semi_sync_master_clients:檢查半同步的slave個數 
Rpl_semi_sync_master_status:1表示主庫的半同步功能開啓而且運行正常,0表示主庫的半同步功能關閉或者半同步複製已經變成了異步複製 
Rpl_semi_sync_master_no_tx:表示有多少提交沒有收到slave的確認消息 
Rpl_semi_sync_master_yes_tx:表示有多少個提交收到了slave的確認消息 
Rpl_semi_sync_slave_status:1表示備庫上slave功能開啓而且運行正常,0表示功能未開啓或者運行異常 

3.五、半同步測試

#從庫關閉IO線程
mysql> STOP SLAVE IO_THREAD;

#主庫執行update數據操做,須要等待60秒才能返回
mysql> update temp set name='ddd' where id=1;
Query OK, 1 row affected (1 min 0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

#超時返回以後,從庫的半同步狀態變成OFF狀態
mysql> show status like '%Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_status                | OFF   |

#當從庫同步正常後,半同步狀態顯示正常
mysql> START SLAVE IO_THREAD;
mysql> show status like '%Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_status                | ON    | 

---------------------------------------------------------------------------------
#當有兩個從庫都開啓半同步複製時,中止其中一個的slave IO線程,再在主庫上執行插入,操做很快返回
#當把第二個從庫的slave IO線程關閉時,則主庫插入數據須要等待60秒才能返回

4、MySQL基於GTID的複製

傳統主從複製弊端:

Failover(故障轉移)問題?
一、監控問題? 主機、mysql實例
二、處理裏的問題,須要人爲
三、數據補償---->GTID
---------------------------------------------------

#描述環境:
一、1主2從的wordpress 生產環境,(db01(M)  db02(s1)  db03(s2))
二、wordpress應用默認是鏈接到db01這個主庫的
三、db01宕機
四、wordpress應用是沒有能力和責任監控到db01宕機。
五、人爲的實時監控到db01宕機。
六、選擇一個新的主庫(New Master),原則更加接近主庫數據狀態的從庫
七、選擇方法:在每一個從庫重運行:
		show slave status\G 
		Master_Log_File: mysql-bin.000005
        Read_Master_Log_Pos: 120
八、假設s1從庫被選爲新主庫,須要進行數據補償。
8.1若是能經過ssh鏈接上主庫,
(1)當即保存缺失部分的二進制日誌
(2)s2作一樣的操做便可
8.2 若是不能ssh到主庫
(1)計算s2和s1之間的relay-log的差別日誌(在傳統的複製環境中,可能須要比較複雜的對比過程)
因此咱們能夠考慮使用GTID方式構建主從,主庫發生的全部事務都會打上一個惟一的標標籤,並且是全局
惟一的。基於GTID全局惟一的特性,很容易判斷s1和s2 relay-log數據差別。
(2)S2 獲取差別部分的relay-log日誌,恢復到當前庫,兩個從庫之間的數據就一致了。	
九、s2從新指向(change master to 到s1)s1

傳統複製與GTID複製區別:

#傳統複製
CHANGE MASTER TO
  MASTER_HOST='10.0.0.51',
  MASTER_USER='repl',
  MASTER_PASSWORD='123',
  MASTER_PORT=3307,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=444,
  MASTER_CONNECT_RETRY=10;

#GTID複製 
change master to 
master_host='10.0.0.51',
master_user='repl',
master_password='123' ,
MASTER_AUTO_POSITION=1;
--------------------------------------------------------------------------

start slave;

(0)在主從複製環境中,主庫發生過的事務,在全局都是由惟一GTID記錄的,更方便Failover
(1)額外功能參數(3個):
      gtid-mode = on 
      enforce-gtid-consistency = on 
      log_slave_updates(5.6須要開啓)
(2)change master to 的時候再也不須要binlog 文件名和position號,MASTER_AUTO_POSITION=1;
(3)在複製過程當中,從庫再也不依賴master.info文件,而是直接讀取最後一個relaylog的 GTID號
(4) mysqldump備份時,默認會將備份中包含的事務操做,以如下方式
	SET @@GLOBAL.GTID_PURGED='8c49d7ec-7e78-11e8-9638-000c29ca725d:1';
	告訴從庫,個人備份中已經有以上事務,你就不用運行了,直接從下一個GTID開始請求binlog就行。

4.一、GTID簡介

1)GTID(global transaction identifiers)複製是徹底基於事務的複製,即每一個在主庫上執行的事務都會被分配一個惟一的全局ID並記錄和應用在從庫上,這種複製方式簡化了創建slave和master/slave之間切換的工做,由於其徹底不須要找當前執行的bin log和log中的位置完成切換  ==>核心特性: 全局惟一,具有冪等性

2)一個GTID是master上執行的任何commit事務所分配的全局惟一ID標示,其由兩部分組成

GTID = source_id:transaction_id

#Source_id表明主庫的server_uuid
#transaction_id表明事務按順序提交的ID,好比第一個提交則是1,第十個提交的事務就是10
#GTID集合表明一組GTID

4.二、GTID複製原理

1)當一個事務在主庫提交時,該事務就被賦予了一個GTID,並記錄在主庫的binary log

2)主庫的binary log會被傳輸到從庫的relay log中,從庫讀取此GTID並生成gtid_next系統參數

3)從庫驗證此GTID並無在本身的binary log中使用,則應用此事務在從庫上

4.三、MySQL5.6與5.7 GTID區別

1)MySQL5.6的GTID複製模式,slave必須開啓bin-log和log_slave_updates參數,不然啓動就報錯,由於須要在binlog找到同步複製的信息(UUID:事務號) (注:開啓log_slave_updates參數,是把relay-log裏的日誌內容再記錄到slave本地的binlog裏。

2)但在MySQL5.7裏,官方作了調整,用一張gtid_executed系統表記錄同步複製的信息(UUID:事務號),這樣就能夠不用開啓log_slave_updates參數,減小了從庫的壓力

3)從MySQL5.7.4版本開始,GTID會存放在mysql系統庫的gtid_executed表中

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) )

4.四、GTID複製配置

假定兩個數據庫實例間的主從關係已經經過傳統模式建立好了

1)關閉主庫和從庫

shell> mysqladmin -uusername -p shutdown

2)設置主從庫GTID後啓動 並暫時關閉slave進程

#主庫
[root@master ~]# cat /etc/my.cnf
[mysqld]
gtid-mode = on 
enforce-gtid-consistency = on 

#從庫
[root@slave ~]# cat /etc/my.cnf
[mysqld]
gtid-mode = on
enforce-gtid-consistency = on  #是確保只有對gtid複製機制安全的語句纔會被log

3)重啓主從實例,從新設置主從庫的複製關係

若是以前是傳統主從複製,須要在從庫上執行:stop slave;和reset slave all;

CHANGE MASTER TO MASTER_HOST='10.0.0.51', 
MASTER_PORT=3306, 
MASTER_USER='repl', 
MASTER_PASSWORD='mysql', 
MASTER_AUTO_POSITION = 1;  #添加這一行

4)啓動slave

mysql> START SLAVE;

7)測試

#從庫上gtid表(主庫和從庫都有)
mysql> select * from mysql.gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| 21d792f0-ebef-11e9-9252-000c29db13e4 |              1 |            4 |
| 21d792f0-ebef-11e9-9252-000c29db13e4 |              5 |            5 |
| 21d792f0-ebef-11e9-9252-000c29db13e4 |              6 |            6 |
| 21d792f0-ebef-11e9-9252-000c29db13e4 |              7 |            7 |
+--------------------------------------+----------------+--------------+

4.五、使用GTID複製的限制條件

1)因爲GTID複製是依賴於事務的,因此MySQL的一些屬性不支持。當一個事務中既包含對InnoDB表的操做,也包含對非事務型存儲引擎表(MyISAM)的操做時,就會致使一個事務中可能會產生多個GTID的狀況;或者是當master和slave的表使用的存儲引擎不同時,都會致使GTID複製功能不正常

mysql> create table temp2(id int,name varchar(10)) engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into temp2 select * from temp;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update temp set name='abc';
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0

mysql> insert into temp2 select * from temp;
ERROR 1785 (HY000): Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables.

2)create table…select語句在基於語句複製的環境中是不安全的,在基於行復制的環境中,此語句會被拆分紅兩個事件,一是建立表,二是insert數據,在某些狀況下這兩個事件會被分配相同的GTID,而致使insert數據的操做被忽略,因此GTID複製不支持create table … select語句

mysql> create table temp2 select * from temp;
ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.

3)create/drop temporary table語句在GTID複製環境中不能放在事務中執行,只能單獨執行,而且autocommit要開啓

4)sql_slave_skip_counter語句是不支持的,若是想要跳過事務,可使用gtid_executed變量

4.六、GTID故障處理

4.6.一、GTID 從庫誤寫入操做處理

報警信息:

#從庫寫入
Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can't create database 'mmm'; database exists' on query. Default database: 'mmm'. Query: 'create database mmm'

Retrieved_Gtid_Set: 21d792f0-ebef-11e9-9252-000c29db13e4:6-11
Executed_Gtid_Set: 21d792f0-ebef-11e9-9252-000c29db13e4:1-10

解決方法:注入空事務

stop slave;
set gtid_next='21d792f0-ebef-11e9-9252-000c29db13e4:11';
begin;commit;
set gtid_next='AUTOMATIC';
start slave;
	
#這裏的xxxxx:N 也就是你的slave sql thread報錯的GTID,或者說是你想要跳過的GTID。
#最好的解決方案:從新構建主從環境
相關文章
相關標籤/搜索