我是導遊
爲什麼會用到MySQL主從架構?
1.做數據的熱備,將從庫作爲後備數據庫,主數據庫服務器故障後,可切換到從數據庫繼續工作,避免數據丟失。
2.滿足業務需求,當業務量越來越大,O/I頻率越來越高,單個主機已經無法滿足需求,增添架構,可以分擔業務量,提升O/I性能,也就是所謂的負載均衡。
3.爲MySQL其他架構做基礎,例如:讀寫分離,高可用。
什麼是MySQL主從複製(REPLICATION)?
通過字面上來看,最起碼要有兩臺數據庫,並且他們的關係是主與從。MySQL主從複製就是將數據庫羣中一臺或多臺服務器作爲主(master)數據庫,其他數據庫作爲從(slave)數據庫,然後指向主庫,實時同步主庫中的數據;當主庫數據發生變化時,會將變化的數據實時同步到一個或多個從庫。
MySQL主從複製過程
其中涉及到了三個線程和兩個日誌:
Binary log(二進制日誌)和Binary log Jump Thread(二進制日誌線程)屬於主數據庫。
I/OThread(輸入/輸出線程),Relay Log(中繼日誌)和SQL Thread(SQL線程)屬於從數據庫。
對於日誌就不用多說了,不管是二進制日誌還是中繼日誌,其中存放的都是SQL語句。
線程解釋:
Binary log dump 線程
當從節點連接主節點後,主節點會創建一個log dump線程,用於發送binlog日誌中的內容。
I/O線程
當從節點執行"start slave"命令後,從節點會創建一個I/O線程用來連接主節點,請求主庫更新的binlog日誌。I/O線程接收到主節點log dump線程發來的更新數據之後,保存到本地的relay log日誌。
SQL線程
SQL線程讀取relay log日誌中的內容,然後解析成具體的SQL語句並執行,最終完成數據同步。
主從複製過程:
1)主節點數據更新,隨後將具體的更新語句寫到binlog日誌中。
2)從節點開啓主從複製功能,創建一個I/O線程,連接主節點。
3)主節點接收到從節點的連接後,創建一個binary log dump線程,把binlog日誌中更新的內容發送到從節點。
4)從節點的I/O線程讀取主節點發送的binlog日誌,並寫入到relay log中。
5)從庫創建SQL線程,讀取relay log日誌中的內容,並解析執行,完成數據同步。
以上描述是一主一從架構,若是其他架構,其原理也是一樣的,只不過細節上稍微有一點不一樣。例如:一主多從架構,在主從複製時,主節點會分別爲每個從節點創建一個binary log dump線程傳遞更新數據,而從節點使用各自的I/O線程和SQL線程。
二進制日誌格式
MySQL的三種複製方式:
基於SQL語句複製(statement-based replication,簡稱SBR)
基於行的複製(row-based replication,簡稱RBR)
混合模式複製(mixed-based replication,簡稱MBR)
根據不同的方式,binlog日誌的格式也有三種,分別是:STATEMENT(基於SQL語句複製),ROW(基於行的複製),MIXED (混合模式複製)。
STATEMENT模式(SBR)
會將數據修改的SQL語句寫到binlog日誌中,無需記錄每行數據變化,減少了日誌量,但有些數據無法保存,不能保證數據的一致性。
ROW模式(RBR)
此模式爲默認。
僅記錄數據被修改,修改成什麼樣子,不記錄SQL語句信息,很大程度上保證了數據的一致性,但會產生大量的日誌。
MIXED模式(MBR)
結合STATEMENT模式和ROW模式使用,優先使用STATEMENT模式保存binlog,對於STATEMENT模式無法保存的數據,則使用ROW模式進行保存。對於STATEMENT模式是否能夠保存數據,由MySQL自行判斷。
MySQL主從複製模式
全同步模式
主庫執行完一個事務後,所有從庫也執行該事務,當所有從庫都執行完該事務後才返回給客戶端。
優點:確保數據的一致性
缺點:性能影響嚴重
異步複製
此模式爲默認。
主庫執行完一個事務後,立即將更新數據發送給從庫,並不關心從庫是否接收。
優點:減少部分資源消耗
缺點:無法確認從庫是否複製成功
半同步模式
相當於異步複製的改良版,主庫執行完事務後,至少一個從庫接收並寫入到relay log中才返回給客戶端。
優點:確保從庫複製成功
缺點:這個過程需要花費一部分時間
MySQL架構方案
一主一從
提升負載均衡
一主多從
提升負載均衡,可用於高可用和讀寫分離,但主節點I/O壓力較大。
多主一從
適用於寫操作較爲頻繁的環境。
互爲主從
也叫做雙主互備,用於讀寫操作都較爲頻繁的環境。
注:有人說這個架構可以提供負載均衡,我個人認爲對的,但是每當有一個庫數據更新,另一個庫都需要消耗一部分資源來進行同步數據,架構還不如使用一主一從。
聯機複製
將一臺從庫作爲中繼,減輕主庫的I/O壓力。
更改二進制日誌格式
對於二進制日誌的保存操作,默認的ROW格式並不是一個很好的選擇,其會產生大量的日誌數據,對後續的主從複製效率不高。
查看binlog格式
mysql> show variables like "binlog_format";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
其實不管是主從架構,還是單純的保存binlog日誌,ROW格式都不是最好的選擇,建議使用MIXED格式,其結合STATEMENT模式和ROW模式保存數據,即能減少日誌的大小,又能確保數據的完整。
直接編輯/etc/my.cnf配置文件,在其中指定binlog日誌格式即可。
binlog-format=MIXED
隨後重啓數據庫,刷新配置。
/etc/init.d/mysql.server restart
再次進入到數據庫中查看binlog日誌格式
mysql> show variables like "binlog_format";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+
已成功更改爲MIXED模式。
MySQL主從複製部署
以一主一從爲例,列舉了MySQL架構的搭建過程。
環境準備
系統版本/MySQL版本 | 主機名 | IP地址 | 角色 | 準備 |
---|---|---|---|---|
CentOS7.7/MySQL8.0.13 | linux.node1 | 192.168.1.123 | master | 關閉防火牆,selinux |
CentOS7.7/MySQL8.0.13 | linux.node2 | 192.168.1.123 | slave | 關閉防火牆,selinux |
一主一從架構部署
1)搭建時間同步服務
對於數據的實時同步,若兩臺服務器的時間都對不上,又談何而來的實時同步呢?
主節點安裝NTP服務
yum install -y ntp
修改ntp服務的配置文件,路徑位於 /etc/ntp.conf ,並添加以下兩項
server 127.127.1.0 #權威NTP不可用時,本機時間作爲時間服務
fudge 127.127.1.0 stratum 8 #NTP服務的階級層數,同步上層服務器的stratum 大小不能超過或等於16。
開啓服務
systemctl start ntpd
查看端口
netstat -anpu | grep ntpd
udp 0 0 192.168.122.1:123 0.0.0.0:* 2726/ntpd
udp 0 0 192.168.1.123:123 0.0.0.0:* 2726/ntpd
udp 0 0 127.0.0.1:123 0.0.0.0:* 2726/ntpd
udp 0 0 0.0.0.0:123 0.0.0.0:* 2726/ntpd
udp6 0 0 fe80::8c62:89:ad82::123 :::* 2726/ntpd
udp6 0 0 ::1:123 :::* 2726/ntpd
udp6 0 0 :::123 :::* 2726/ntpd
從節點安裝ntp客戶端
yum install -y ntpdate
與主節點同步時間
ntpdate 192.168.1.123
19 Jun 16:31:27 ntpdate[61266]: adjust time server 192.168.1.123 offset 0.459178 sec
顯示將時間偏移了0.459178秒,時間同步成功。
注:以下爲主節點配置
2)創建測試數據
mysql> create database replication;
mysql> use replication;
mysql> create table test(id int,name varchar(233));
mysql> insert into test values(1,'一主一從');
3)創建主從複製授權用戶
mysql> create user 'slave'@'192.168.1.%' identified by '123456';
mysql> grant replication slave on *.* to 'slave'@'192.168.1.%';
mysql> flush privileges;
4)修改my.cnf文件
以下爲添加配置項
server-id=1
binlog-format=MIXED
log-bin=/data/mysql/log/mysql-bin-master
binlog-do-db=replication
#binlog-ignore-db=mysql
server-id: mysql的同步的數據中是包含server-id的,用於標識該語句最初是從哪個server寫入,不同節點的server-id不能相同。
binlog-format:binlog日誌格式
log-bin:binlog日誌存放路徑
binlog-do-db:指定binlog日誌保存哪個庫的數據記錄,不添加爲全庫。
binlog-ignore-db:指定binlog日誌不保存哪個庫的數據記錄,不添加爲全部不保存。(若有binlog-do-db配置項,則只保存其指定的庫)
重啓數據庫,刷新配置
/etc/init.d/mysql.server restart
5)查看生成的二進制日誌
ls /data/mysql/log/
mysql-bin-master.000001 mysql-bin-master.index mysqld.log
數據庫中查看
mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin-master.000001
Position: 155
Binlog_Do_DB: replication
Binlog_Ignore_DB: mysql
Executed_Gtid_Set:
6)將主庫的數據傳入從庫
mysqldump -uroot replication > db.sql
scp db.sql root@192.168.1.124:~
The authenticity of host '192.168.1.124 (192.168.1.124)' can't be established.
ECDSA key fingerprint is SHA256:dt6xhgOGH0g33XrYjk1qPbtD4C2hg62DlqfRMoUSK88.
ECDSA key fingerprint is MD5:9b:ef:79:5b:01:9e:63:0d:75:a7:c7:3e:62:a7:6a:04.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.124' (ECDSA) to the list of known hosts.
root@192.168.1.124's password:
db.sql 100% 1817 2.3MB/s 00:00
注:以下爲從節點配置
7)從庫將SQL腳本導入庫中
mysql -uroot -e "create database replication;"
mysql replication < db.sql
查看數據是否導入成功
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| replication |
| sys |
+--------------------+
8)修改my.cnf文件
在原有基礎上添加以下配置項
server-id=2
relay-log=/data/mysql/log/relay-log-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
#replicate_do_db=replication
server-id:服務器ID號
relay-log:relay-log日誌存放路徑
relay-log-index:relay-log日誌的索引文件存放路徑
replicate_do_db:指定從庫複製的數據庫
重啓服務,刷新配置
/etc/init.d/mysql.server restart
9)測試授權用戶是否可以登錄主庫
mysql -uslave -h192.168.1.123 -p123456
登錄進去後,查看其中的數據庫
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
+--------------------+
因爲只有主從複製權限,其他權限沒有開放,所以是看不到其他庫的,但不影響查看數據庫的命令執行。
10)從庫使用授權用戶連接主庫
這裏的授權用戶是由主庫創建的,本案例中的爲slave。
數據庫默認是開啓主從複製的,先關閉
mysql> stop slave;
連接主庫,具體參數根據實際情況指定
mysql> change master to master_host='192.168.1.123',master_user='slave',master_password='123456',master_log_file='mysql-bin-master.000001',master_log_pos=155;
以下爲此案例中主庫的binlog日誌文件,用於理解命令
mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin-master.000001
Position: 155
Binlog_Do_DB: replication
Binlog_Ignore_DB: mysql
Executed_Gtid_Set:
解讀:
master_host:主庫IP地址
master_user:主庫授權用戶
master_password:主庫授權用戶密碼
master_log_file:主庫binlog日誌文件名稱
master_log_pos:主庫binlog日誌文件位置
開啓主從複製功能
mysql> start slave;
11)分別在主庫和從庫中查看主從複製狀態
從庫中查看
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.123
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin-master.000001
Read_Master_Log_Pos: 155
Relay_Log_File: relay-log-bin.000002
Relay_Log_Pos: 329
Relay_Master_Log_File: mysql-bin-master.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB: replication
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: 155
Relay_Log_Space: 535
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: 1b3423c4-b047-11ea-bfaa-000c29bbe2d8
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
其中 Slave_IO_Running和Slave_SQL_Running線程爲YES,表示主庫連接成功,也就是說主從複製搭建成功了。有一個爲Connecting,都表示主從複製沒有搭建成功。
主庫中查看
mysql> show processlist\G
...
*************************** 3. row ***************************
Id: 18
User: slave
Host: 192.168.1.124:43856
db: NULL
Command: Binlog Dump
Time: 716
State: Master has sent all binlog to slave; waiting for more updates
Info: NULL
可以看到binlog dump線程已經建立,連接的主機爲192.168.1.124。
12)驗證主從複製功能
主庫現有數據
mysql> select * from replication.test;
+------+--------------+
| id | name |
+------+--------------+
| 1 | 一主一從 |
+------+--------------+
從庫現有數據
mysql> select * from replication.test;
+------+--------------+
| id | name |
+------+--------------+
| 1 | 一主一從 |
+------+--------------+
在主庫中插入數據
mysql> insert into replication.test values(2,'測試');
在從庫中查看數據是否同步成功
mysql> select * from replication.test;
+------+--------------+
| id | name |
+------+--------------+
| 1 | 一主一從 |
| 2 | 測試 |
+------+--------------+
若是主從狀態正常,但數據沒有同步成功,那一定概率就是主庫的binlog日誌位置變了,重新查看主庫的binlog日誌位置,再次連接主庫即可。
或者說刪除binlog日誌(reset master),重新創建並連接。