主從複製
介紹:
兩臺或以上的數據庫實例,通過binlog實現,數據異步同步的關係。
主從複製的搭建
2臺以上的MySQL實例(同版本、同平臺),具備不同的server_id,server_uuid
3307:主庫
3308:從庫
3309:從庫
[root@db01 3308]# systemctl start mysqld3307
[root@db01 3308]# systemctl start mysqld3308
[root@db01 3308]# systemctl start mysqld3309
[root@db01 3308]# mysql -S /tmp/mysql3307.sock -e "select @@server_id ;"
+-------------+
| @@server_id |
+-------------+
| 7 |
+-------------+
[root@db01 3308]# mysql -S /tmp/mysql3308.sock -e "select @@server_id ;"
+-------------+
| @@server_id |
+-------------+
| 8 |
+-------------+
[root@db01 3308]# mysql -S /tmp/mysql3309.sock -e "select @@server_id ;"
+-------------+
| @@server_id |
+-------------+
| 9 |
+-------------+
[root@db01 3308]# mysql -S /tmp/mysql3309.sock -e "select @@server_uuid ;"
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 1c920eb6-901a-11ea-a2a5-000c29248f69 |
+--------------------------------------+
[root@db01 3308]# mysql -S /tmp/mysql3308.sock -e "select @@server_uuid ;"
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 195bb724-901a-11ea-a083-000c29248f69 |
+--------------------------------------+
[root@db01 3308]# mysql -S /tmp/mysql3307.sock -e "select @@server_uuid ;"
+--------------------------------------+
| @@server_uuid |
+--------------------------------------+
| 15ac32d2-901a-11ea-9ee5-000c29248f69 |
+--------------------------------------+
[root@db01 3308]#
主庫:開啓binlog日誌 創建複製用戶
vim /data/3307/my.cnf
server_id=7
log_bin=/data/3307/mysql-bin
[root@db01 3308]# systemctl restart mysqld3307
[root@db01 3308]# mysql -S /tmp/mysql3307.sock -e "select @@log_bin ;"
[root@db01 3308]# mysql -S /tmp/mysql3307.sock -e "grant replication slave on *.* to repl@'10.0.0.%' identified by '123';"
[root@db01 3308]# mysql -S /tmp/mysql3307.sock -e "select user,host ,plugin from mysql.user;"
補課 備份主庫數據 恢復到從庫
[root@db01 3308]# mysqldump -S /tmp/mysql3307.sock -A --master-data=2 --single-transaction -R -E --triggers --max_allowed_packet=64M >/data/full.sql
[root@db01 3308]# mysql -S /tmp/mysql3308.sock</data/full.sql
[root@db01 3308]# mysql -S /tmp/mysql3309.sock</data/full.sql
告知從庫複製的信息
(change master to user,password, ip ,port, filename、pos )
help change master to
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;
vim /data/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=444;
啓動線程
start slave;
查看複製狀態
[root@db01 3308]# mysql -S /tmp/mysql3309.sock -e "show slave status\G"|grep "Running:"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@db01 3308]# mysql -S /tmp/mysql3308.sock -e "show slave status\G"|grep "Running:"
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[root@db01 3308]#
主從複製原理
記住三個線程 (dump IO SQL) 四個文件(主庫binlog 從庫relaylog relaylog.info master.info
1、在從庫執行change master to… 此時會將change master to…;中指定的主庫信息記錄到master.info文件中,然後通過slave線程和SQL線程;
2、IO線程讀取master.info文件中連接信息發起連接請求到達主機庫所在主機的連接層與dump線程建立連接
3、IO線程通過已經建立的鏈接請求主庫生成的binlog數據;
4、主庫dump線程響應從庫的IO線程的請求返回對應的binlog數據。
5、IO線程接收到數據將其保存到relay log中,並更新此時的接受狀態信息到master.info中
6、SQL線程讀取relay.info中當前的回放狀態信息,然後從relaylog中讀取並回放最新的日誌
7、回放完畢後將最新的回放狀態更新到relaylog中。
涉及到的線程
主庫:
binlog_dump_thread 負責接受slave請求和傳送主庫binlog給slave
mysql> show processlist;
+----+------+------------+------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+------------+------+-------------+------+---------------------------------------------------------------+------------------+
| 6 | repl | db01:34638 | NULL | Binlog Dump | 2045 | Master has sent all binlog to slave; waiting for more updates | NULL |
| 7 | repl | db01:34640 | NULL | Binlog Dump | 2015 | Master has sent all binlog to slave; waiting for more updates | NULL |
| 8 | root | localhost | NULL | Query | 0 | starting | show processlist |
+----+------+------------+------+-------------+------+---------------------------------------------------------------+------------------+
從庫:
IO線程
連接主庫dump線程 請求master日誌、接受master日誌、存儲日誌(relaylog)
SQL線程
回放relaylog
mysql> show slave status \G
涉及到的文件
主庫:
binlog日誌文件
從庫:
relaylog中繼日誌
命名方式:
datadir/HOSTNAME-relay-bin.00000N
作用: 存儲獲取到的binlog
主庫信息文件
命名方式:datadir/master.info
作用:記錄主庫ip port user password binlog 位置點信息
中繼日誌應用信息
命名方式:
relay-log.info
作用: 記錄SQL 線程回放到的位置點信息。
如何監控主從複製
主庫
[root@db01 data]# mysql -S /tmp/mysql3307.sock -e "show processlist" |grep "Dump"
7 repl db01:34640 NULL Binlog Dump 5355 Master has sent all binlog to slave; waiting for more updates NULL
9 repl db01:34642 NULL Binlog Dump 687 Master has sent all binlog to slave; waiting for more updates NULL
[root@db01 data]# mysql -S /tmp/mysql3307.sock -e "show slave hosts;"
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 9 | | 3309 | 7 | 1c920eb6-901a-11ea-a2a5-000c29248f69 |
| 8 | | 3308 | 7 | 195bb724-901a-11ea-a083-000c29248f69 |
+-----------+------+------+-----------+--------------------------------------+
從庫
[root@db01 data]# mysql -S /tmp/mysql3308.sock -e "show slave status \G"
主庫連接信息、binlog位置信息(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
從庫中relay-log的回放信息(relay-log.info)
Relay_Log_File: db01-relay-bin.000006
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Exec_Master_Log_Pos: 444
線程監控信息:主要用來排查主從故障
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
過濾複製相關信息
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
落後於主庫的秒數
Seconds_Behind_Master: 0
延時從庫狀態信息
SQL_Delay: 0
SQL_Remaining_Delay: NULL
GTID複製信息
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
一堆position功能
(1) IO 已經獲取到的主庫Binlog的位置點(master.info)
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 444
作用: IO下次請求日誌時,起點位置。
(2) SQL 回放到的relaylog位置點。(relay-log.info)
Relay_Log_File: db01-relay-bin.000006
Relay_Log_Pos: 320
(3)SQL回放的realylog位置點,對應的主庫binlog的位置點(relay-log.info)
Relay_Master_Log_File: mysql-bin.000001
Exec_Master_Log_Pos: 600
作用: 計算主從複製延時日誌量。
主從複製故障
如何監控
[root@db01 data]# mysql -S /tmp/mysql3308.sock -e "show slave status \G"
Slave_IO_Running: Yes # IO線程工作狀態: YES、NO、Connecting
Slave_SQL_Running: Yes # SQL線程工作狀態:YES、NO
Last_IO_Errno: 0 # IO故障代碼:2003,1045,1040,1593,1236
Last_IO_Error: # IO線程報錯詳細信息
Last_SQL_Errno: 0 # SQL故障代碼: 1008,1007
Last_SQL_Error: # IO線程報錯詳細信息
從庫的錯誤日誌
IO線程故障
連接主庫失敗
## user,password,IP,Port,plugin
## 主庫無法連接:網絡、宕機、防護牆、最大連接數上限
故障模擬:
(1)主庫宕機
systemctl stop mysqld3307
show slave status\G
還原:
systemctl start mysqld3307
mysql -S /tmp/mysql3308.sock -e "start slave;"
(2) 模擬用戶密碼錯誤
mysql -S /tmp/mysql3307.sock -e "alter user repl@'10.0.0.%' identified by '11212'"
mysql -S /tmp/mysql3308.sock -e "start slave; show slave status\G "
還原:
mysql -S /tmp/mysql3307.sock -e "alter user repl@'10.0.0.%' identified by '123'"
mysql -S /tmp/mysql3308.sock -e "start slave; show slave status\G "
(3) 連接數上限
mysql -S /tmp/mysql3307.sock -e " set global max_connections=2;"
mysql -S /tmp/mysql3307.sock
mysql -S /tmp/mysql3307.sock
mysql -S /tmp/mysql3308.sock -e "stop slave; start slave; show slave status\G "
還原:
mysql -S /tmp/mysql3307.sock -e " set global max_connections=200;"
mysql -S /tmp/mysql3308.sock -e "stop slave; start slave; show slave status\G "
排查方法:
[root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P 3300
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2003 (HY000): Can't connect to MySQL server on '10.0.0.51' (111)
[root@db01 ~]# mysql -urepl -p123 -h 10.0.0.52 -P 3307
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2003 (HY000): Can't connect to MySQL server on '10.0.0.52' (113)
[root@db01 ~]# mysql -urepla -p123 -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 'repla'@'db01' (using password: YES)
[root@db01 ~]# mysql -urepl -p1123 -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)
[root@db01 ~]#
請求日誌
主庫日誌損壞、缺失
。
主從的server_id、Server_uuid相同
。
server_id 故障重現:
[root@db01 ~]# mysql -S /tmp/mysql3307.sock
mysql> set global server_id=8;
[root@db01 ~]# mysql -S /tmp/mysql3307.sock
mysql> select @@server_id;
[root@db01 ~]# mysql -S /tmp/mysql3308.sock
mysql> stop slave;start slave;show slave status;
回退:
[root@db01 ~]# mysql -S /tmp/mysql3307.sock
mysql> set global server_id=7;
[root@db01 ~]# mysql -S /tmp/mysql3307.sock
mysql> select @@server_id;
[root@db01 ~]# mysql -S /tmp/mysql3308.sock
mysql> start slave;show slave status;
主庫日誌損壞故障重現:
[root@db01 ~]# mysql -S /tmp/mysql3307.sock
mysql> reset master;
[root@db01 ~]# mysql -S /tmp/mysql3308.sock
mysql> start slave;show slave status;
測試環境處理方法(主從的數據當前是一致的):
[root@db01 ~]# mysql -S /tmp/mysql3308.sock
#將所有線程停止。
mysql> stop slave;
將從庫複製信息清空(master.info,relay-log.info清空,show slave status看不到信息了)
mysql> reset slave all;
mysql> 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=154,
MASTER_CONNECT_RETRY=10;
mysql> start slave;
生產中需要額外考慮什麼情景?
需要重構主從:
1. 備份恢復.
2. change master to ; start slave
SQL線程故障
SQL線程主要工作: 回放relaylog中的日誌事件,可以理解爲後臺執行SQL語句。
realy-log 損壞
。
處理方法: 重構。
方法1: 備份主庫+change master to + start slave;
方法2: 找到問題點+ change master + start slave;
思路: 如何找到問題位置點。
1. 找到SQL已經回放到什麼位置了。
SQL回放的realylog位置點,對應的主庫binlog的位置點(relay-log.info)
Relay_Log_File: db01-relay-bin.000006
Relay_Log_Pos: 320
----》
2. 找到主庫相應位置點:
Relay_Master_Log_File: mysql-bin.000001
Exec_Master_Log_Pos: 600
3. change master to mysql-bin.000001 600
執行SQL出問題?
(1)主從節點配置不一樣: 平臺、版本、參數、SQL_MODE
調整成一致。
(2)修改的對象不存在(庫、表、用戶)
從庫被寫入了。 雙主架構。異步方式主從,導致數據不一致。
(3)創建的對象已存在(庫、表、用戶、約束衝突)
從庫被寫入了。 雙主架構。
方法一:部分場景可以使用,只要保證數據以主庫爲準即可使用。
stop slave;
set global sql_slave_skip_counter = 1;
#將同步指針向下移動一個,如果多次不同步,可以重複操作。
start slave;
方法二:不推薦
/etc/my.cnf
slave-skip-errors = 1032,1062,1007
常見錯誤代碼:
1007:對象已存在
1032:無法執行DML
1062:主鍵衝突,或約束衝突
總結: SQL線程故障規避方法
- 從庫只讀 ,讀寫分離中間件。
- 不使用雙主結構。PXC、MGR替代。
- 半同步、增強半同步複製等,或者PXC、MGR替代。