概述:
MySQL 的主從複制是通過他的歸檔日志(binlog) 來實作的。基本的過程就是從庫在一個線程中和主庫建立一個長連接配接,告訴主庫從主庫同步的 binlog 的位置,然後主庫将這個位置之後的 binlog 日志内容發送給從庫,從庫擷取到主庫發送過來的 binlog 内容後先寫入到本地的中轉日志(relaylog)中,然後從庫另一個程序在從中轉日志中讀取内容并解析成為 sql 語句在從庫中執行,進而保證了主從的同步。
要設定主從複制,有幾個前提:
以mysql8為例
- 首先,主庫和從庫的資料庫的大版本保持一緻。
- 第二,主從複制叢集中每個資料庫執行個體的 server-id 的值不能重複。(線上執行個體的server-id 生成政策已經避免重複,無需操作)
- 第三,要開啟歸檔日志并且歸檔日志的格式選擇為 row 方式。這兩個在 MySQL 8 中預設就是這樣,是以不需要設定,如果早期版本預設值不同需要在配置檔案中人工設定。
步驟:
一主一從複制
參數說明
repl :進行主從複制權限的使用者名
123456 :進行主從複制權限的密碼
30.40.36.86 :slave節點的IP
10.218.251.172:master節點的IP
主庫設定
首先在在 MySQL 中增加一個可以進行主從複制權限的使用者。在 mysql 互動環境中執行如下指令:
mysql> create user 'repl'@'30.40.36.86' identified by '123456';
mysql> grant replication slave on *.* to 'repl'@'30.40.36.86';
mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 2507 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
最後一個指令擷取到目前歸檔日志的名字和位置,後面從伺服器設定主從複制的時候需要從這個位置開始。
從庫設定
1.基本設定
得到上面這些資訊後,我們就可以登入到 slave 伺服器上的資料庫,然後通過下面的指令将這個資料庫設定為 master 資料庫的從伺服器。
mysql> change master to
-> master_host='10.218.251.172',
-> master_port=3306,
-> master_user='repl',
-> master_password='123456',
-> master_log_file='binlog.000001',
-> master_log_pos=2507;
這個指令将目前資料庫設定為 10.218.251.172 資料庫的從庫,并且從歸檔日志 binlog.000001 的位置 2507開始進行複制(在前面已擷取)
2.開啟複制線程
start slave;
不帶任何參數表示同時啟動I/O 線程和SQL線程。
I/O線程從主庫讀取bin log,并存儲到relay log中繼日志檔案中。
SQL線程讀取中繼日志,解析後,在從庫重放。
3.檢視從庫的狀态
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.218.251.172
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 2507
Relay_Log_File: BAB1800793-relay-bin.000002
Relay_Log_Pos: 319
Relay_Master_Log_File: binlog.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: 2507
Relay_Log_Space: 532
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: 11
Master_UUID: 55b5f9f9-6996-11e9-a55e-7cd30ac454c0
Master_Info_File: mysql.slave_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:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
ERROR:
No query specified
注:'\G' 是格式化show的結果,友善檢視
Slave_IO_State 的值為 Waiting for master to send event ,表示已經準備好接受主庫發送過來的歸檔日志進行處理了。也可以看下Slave_IO_Running,Slave_SQL_Running的狀态都為Yes表示I/O 線程和SQL線程都已經啟動成功。
效果示範
1.主庫插入資料
登入主庫執行如下指令
mysql> create database copytest;
mysql> use copytest;
mysql> create table copytable(id int(11));
mysql> insert into copytable values(1);
mysql> select * from copytable;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.03 sec)
2.從庫檢視資料
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| copytest |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
mysql> use copytest;
mysql> show tables;
+--------------------+
| Tables_in_copytest |
+--------------------+
| copytable |
+--------------------+
mysql> select * from copytable;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
可以看到,主庫中做的操作,都同步到從庫中來了。
同步指定的資料庫(表)
注:下面指定資料庫(表)的指令産生的效果沒有儲存下來,如果資料庫重新開機了,那麼就會失效。如果要生效就需要将配置寫在 my.cnf 檔案中。在從庫中,将 my.cnf 檔案内容更改為如下即可。
同步指定的資料庫
上面的設定中,我們是将主庫中的所有資料庫都同步到從庫中來了。實際上,我們還可以通過指令的方式同步指定的資料庫或者資料庫的資料表。在從庫中執行下面的指令将會指定隻同步資料庫copytest。
mysql> stop slave;
mysql> change replication filter replicate_do_db=(copytest);
mysql> start slave;
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.218.251.172
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 3189
Relay_Log_File: BAB1800793-relay-bin.000003
Relay_Log_Pos: 319
Relay_Master_Log_File: binlog.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: copytest
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: 3189
Relay_Log_Space: 1378
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: 11
Master_UUID: 55b5f9f9-6996-11e9-a55e-7cd30ac454c0
Master_Info_File: mysql.slave_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:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
ERROR:
No query specified
注意:執行任何修改同步政策的操作前都需要先停止複制線程。指令:stop slave;
可以看到Replicate_Do_DB的值已經變成了copytest。這樣,隻有主庫中 copytest資料庫中的變化會同步到從庫中來,其餘的資料庫的變化則不會同步。
取消同步指定的資料庫
取消剛才制定的同步資料
mysql> stop slave;
mysql> change replication filter replicate_do_db=();
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 10.218.251.172
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 3189
Relay_Log_File: BAB1800793-relay-bin.000004
Relay_Log_Pos: 319
Relay_Master_Log_File: binlog.000001
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: 3189
Relay_Log_Space: 696
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: 11
Master_UUID: 55b5f9f9-6996-11e9-a55e-7cd30ac454c0
Master_Info_File: mysql.slave_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:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
ERROR:
No query specified
同步忽略指定的資料庫
有時候存在除了某一個庫别的庫都需要同步,如果一一把所有需要同步的資料庫設定進去太麻煩,并且新增資料庫由于沒有制定到需要同步的資料庫項裡面導緻無法同步。這個時候就可以制定忽略那些庫不需要同步,指令如下:
mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> change replication filter Replicate_Ignore_DB=(ignoretest);
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.07 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.218.251.172
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 3189
Relay_Log_File: BAB1800793-relay-bin.000005
Relay_Log_Pos: 319
Relay_Master_Log_File: binlog.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB: ignoretest
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: 3189
Relay_Log_Space: 696
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: 11
Master_UUID: 55b5f9f9-6996-11e9-a55e-7cd30ac454c0
Master_Info_File: mysql.slave_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:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
ERROR:
No query specified
mysql>
同步指定的資料表
方法同上,隻是需要制定的參數不同,設定值的時候可以用通配符。需要注意的是需要指定具體某庫的某個(些)表
指令如下:`CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE =('copytest.copytable%');`
代表同步copytest庫下面的所有以copytable開頭的表。
取消指定的資料表
方法同取消指定的資料庫基本相同,指令:`CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE =();`;
多主一從複制(多源複制)
資料流向:
master1 -> slave
master2 -> slave
參數說明
repl :進行主從複制權限的使用者名
123456 :進行主從複制權限的密碼
30.40.36.86 :slave節點的IP
10.218.251.172:master1節點的IP
10.218.251.11 :master2節點的IP
主庫設定
master1設定:
首先在在 MySQL 中增加一個可以進行主從複制權限的使用者。在 mysql 互動環境中執行如下指令:
mysql> create user 'repl'@'30.40.36.86' identified by '123456';
mysql> grant replication slave on *.* to 'repl'@'30.40.36.86';
mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000001 | 3189 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
最後一個指令擷取到目前歸檔日志的名字和位置,後面從伺服器設定主從複制的時候需要從這個位置開始。
master2設定:
同master1相同
mysql> create user 'repl'@'30.40.36.86' identified by '123456';
mysql> grant replication slave on *.* to 'repl'@'30.40.36.86';
mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000095 | 7909238 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
從庫設定
1.基本設定
得到上面這些資訊後,我們就可以登入到 slave 伺服器上的資料庫,然後通過下面的指令将這個資料庫設定為 master 資料庫的從伺服器。
mysql> change master to
-> master_host='10.218.251.172',
-> master_port=3306,
-> master_user='repl',
-> master_password='123456',
-> master_log_file='binlog.000001',
-> master_log_pos=3189
-> for channel '100';
Query OK, 0 rows affected, 1 warning (0.23 sec)
mysql>
mysql> change master to
-> master_host='10.218.251.11',
-> master_port=3306,
-> master_user='repl',
-> master_password='123456',
-> master_log_file='binlog.000095',
-> master_log_pos=7909238
-> for channel '200';
Query OK, 0 rows affected, 1 warning (0.30 sec)
這個指令将目前資料庫設定為 10.218.251.172 和10.218.251.11資料庫的從庫,并且分别記錄歸檔日志 的位置。分别設定了通道,可以同時執行。
注:與一主一從相比多了for channel‘’ 用來指定複制通道。
2.開啟複制線程
start slave;
開啟所有頻道的複制線程。
start slave for channel '100';
隻開啟通道為100的複制線程。
stop slave;
關閉所有頻道的複制線程。
stop slave for channel '100'
隻關閉通道為100的複制線程。
3.檢視從庫狀态
由于有兩個主庫是以會分别統計狀态
mysql> start slave;
Query OK, 0 rows affected (0.08 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.218.251.172
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 3189
Relay_Log_File: BAB1800793-relay-bin-100.000002
Relay_Log_Pos: 319
Relay_Master_Log_File: binlog.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: 3189
Relay_Log_Space: 536
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: 11
Master_UUID: 55b5f9f9-6996-11e9-a55e-7cd30ac454c0
Master_Info_File: mysql.slave_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: 100
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
*************************** 2. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.218.251.11
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000095
Read_Master_Log_Pos: 7909238
Relay_Log_File: BAB1800793-relay-bin-200.000002
Relay_Log_Pos: 319
Relay_Master_Log_File: binlog.000095
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: 7909238
Relay_Log_Space: 536
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: b794dc7e-6958-11e9-bcb2-7cd30ac4546c
Master_Info_File: mysql.slave_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: 200
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
2 rows in set (0.00 sec)
ERROR:
No query specified
可以看見設定三個的主從同步通道的所有狀态資訊。隻有【Slave_IO_Running】和【Slave_SQL_Running】都是Yes,則同步是正常的。 如果是No或者Connecting都不行,可檢視mysql-error.log,以排查問題。
效果示範
1.mater1庫插入資料
mysql> create database testmaster;
mysql> use testmaster;
mysql> create table tablemaster(id int(11));
mysql> insert into tablemaster values(1);
mysql> select * from tablemaster;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.01 sec)
2.mater2庫插入資料
mysql> create database testmaster2;
Query OK, 1 row affected (0.07 sec)
mysql> use testmaster2;
mysql> create table tablemaster2(id int(11));
mysql> insert into tablemaster2 values(1);
mysql> select * from tablemaster2;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.86 sec)
3.檢視從庫變化
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| testmaster |
| testmaster2 |
+--------------------+
6 rows in set (0.00 sec)
mysql> use testmaster;
Database changed
mysql> show tables;
+----------------------+
| Tables_in_testmaster |
+----------------------+
| tablemaster |
+----------------------+
1 row in set (0.00 sec)
mysql> select * from tablemaster;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> use testmaster2;
Database changed
mysql> show tables;
+-----------------------+
| Tables_in_testmaster2 |
+-----------------------+
| tablemaster2 |
+-----------------------+
1 row in set (0.00 sec)
mysql> select * from tablemaster2;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
master1和master2的資料都同步過來了。
注:master1和master2不能同時執行相同的DDL;不能執行有互相沖突的sql語句。是以如果需要同庫的同表需要在開啟同步前定義好資料庫結構。
同步指定資料庫資料
同一主一從類似,不同點就是可以在sql後面加上
for channel 'channelID'
來指定操作的通道,不指定預設全部通道一起執行。
參考文章:
https://www.jianshu.com/p/fc90ad7d34e0