MySQL主從複製(詳細過程以及從庫不能同步的解決辦法)

前面已經在本地搭建了多個MySQL的實例,可以用這些實例進行主從複製。

主要是三個線程,主庫上的binlog dump線程、從庫I/O線程、從庫SQL線程

端口3306的MySQL實例作爲主服務器(master),端口3307、3308的MySQL實例作爲從服務器(slave)

基本過程爲:

1.啓動主庫並配置可以複製的用戶

2.啓動從庫(I/O線程),連接主庫

3.當主庫由相應操作時,保存二進制文件binlog,主庫通過binlog dump線程發送給從庫的I/O線程,I/O線程將binlog中的內容更新到relay log中去(注意:一個主庫對應一個從庫都會有一個binlog dump線程,如果有多個從庫,則主庫會存在多個binlog dump線程)

4.從庫上的SQL線程讀取relay log中的語句並執行。

5.從庫執行完畢之後,刪除relay log,以免relay log太多佔用磁盤空間

補充:

如果從庫宕機恢復之後,從庫如何知道宕機之前在複製到哪了?

從庫會默認創建兩個文件保存複製的進度:master.info、relay-log.info

關於完整的MySQL主從複製文檔,可參見官方文檔,裏面的步驟說的已經很詳細了

1.在master的配置文件中,在[mysqld]下開啓log-bin功能,以及分配一個server-id(server-id官方文檔給出的範圍是1到2^{31}-1)

[mysqld]
server-id = 1
port=3306
socket=/tmp/mysql.sock1
key_buffer_size=16M
max_allowed_packet=8M
datadir=/usr/local/mysql3306/data
basedir=/usr/local/mysql3306
pid-file = /usr/local/mysql3306/data/3306.pid
#開啓mysql的日誌功能
log-bin = mysql-bin
innodb_flush_log_at_trx_commit=1
#每次事務提交,MySQL都會調用文件系統,將binlog刷新到磁盤上,默認爲0,是不開啓的,不建議開啓,如果事務併發提交很多,高頻率對磁盤的IO也會影響MySQL的性能
sync_binlog=0

登錄master,查看log-bin是否已經開啓(ON代表開啓)

show variables like 'log_bin';

在master上創建專門用來複制的用戶(repl-自定義的用戶名,localhost-這裏我填的是本地,如果slave不在你本機,可以填寫slave的IP,12345是此用戶的密碼)

提示:如果是MySQL8的話,默認採用的是caching_sha2_password密碼策略,除非你已經配置了SSL連接,否則,從數據庫連接時依然連不上,如下圖:

select user,host,plugin,authentication_string from user \G

可以將MySQL8的密碼策略修改位mysql_native_password

create user 'repl'@'localhost' identified with 'mysql_native_password' by '12345';

授權

grant replication slave on *.* to 'repl'@'localhost';

重啓master實例,查看用戶是否創建成功,授權是否成功

select user,host from mysql.user;
show grants for 'repl'@'localhost';

如果授權成功,會是下面這樣

授權成功查詢結果

在slave的兩個實例上配置server-id即可,每個實例的server-id要不同.

啓動3307、3308兩個實例,命令行進入slave實例,這裏以3308實例舉例子說明

1.進入3308實例,因爲是一個機器多個實例,所以要指定socket,-S 是3308實例的socket的位置,可在my.cnf配置

 mysql -uroot -p -S /tmp/mysql.sock3

2.對從數據庫進行相應的設置

change master to master_host='localhost',master_user='repl',master_password='12345',master_log_file='mysql-bin.000002',master_log_pos=2123;

 最後兩個參數,master_log_file和master_pos不知道,怎麼辦?

在master實例上查看即可

show master status;

顯示如下圖:

查詢結果

注意最後一個參數是不帶 ' ',不要多寫了

3.設置好之後,啓動slave

start slave;

4.查看(注意,這個SQL結尾是沒有 ;  如果加了 ; 會在最下面看到一個ERROR:No query specified的提示)

show processlist \G

顯示信息

5.接下來則可以在主庫上插入一條數據,測試從庫是否同步過來了

在主庫master插入一條數據之後,查看主庫數據

use dhb(我的一個數據庫);
insert into user (id,name,age) values (111,'測試slave',112);
select * from user;

在從庫slave(3308)上查看

use dhb;
select * from user;

如果查到,則代表同步成功,如果發現從庫沒有更新剛纔主庫插入的那條數據怎麼排查錯誤呢?

在從庫slave上執行(注意:這裏\G後面同樣沒有;)

show slave status \G

重點關注:Last_IO_Error(這裏一般顯示的具體錯誤信息)、Master_Log_File、Read_Master_Log_Pos這三項,後兩項是是否和master實例保持一致

不能複製的錯誤圖

可以看到,這裏的Last_IO_Error,應該是我master_password密碼錯了(或者master沒有啓動SSL連接,具體解決方法在上面),修改slave的master_password即可,修改某一項的參數命令如下:

stop slave;
change master to master_password(修改哪一個參數就寫哪一個,不需要修改的就不寫)='12345';
start slave;

如果想要只複製特定的數據庫、特定的數據表可以 在salve實例的my.cnf配置文件指定即可

replicate-ignore-table = dhb.user
replicate-ignore-db = otherdb
replicate-do-db = dhb
replicate-do-table = dhb.gener

主庫master上所有的insert、update、delete操作以及新建表、修改表、刪除表操作都會同步到從庫slave上。

常見問題:

如果在從庫上刪除了一條記錄,然後在主庫上更新該條記錄(update語句),從庫會更新失敗,

接着,在主庫中新插入一條數據,發現從庫並沒有複製過來,如下圖

報錯信息

出現這個問題是因爲:

如果從庫止執行binlog中的SQL出錯時(比如更新一條從庫裏沒有的數據、或者主鍵衝突),這是從庫會停止複製,不再進行同步,等待用戶介入處理。

處理方法:使用該參數的從庫不是主要當做主庫的備份數據庫,只是查詢數據庫分擔壓力而已,如果該slave被用來當做主庫的備份數據庫,強烈不建議此參數。

#可以使用下面的參數,直接跳過錯誤,繼續執行,其中all代表所有參數,也可以配置一個數組[具體放的是err_code,err_code2,...]
slave-skip-errors = all

如果想要徹底結束主從複製關係,可以

1.在從數據庫上執行
stop slave;
reset slave all;
清除該從服務器和主服務器之間的關係
2.如果主服務器也不維護關係了,則在主服務器上執行
reset master;

其他更多參數master-connect-retry、log-slave-updates,等可參考官方文檔或者MySQL相關書籍

 

拓展:

常見主從架構:

1、一主多從

2、多級複製。如果從庫數量很多,主庫會對每個從庫建立一個binlog dump線程來將數據庫變化發送給從庫的I/O線程。這時候主庫還要承擔大量寫的壓力,整體壓力十分大。可以使用master1->master2->slave1、slave2...slaveN這種架構。也就是說存在兩個主庫,主庫1直接把數據推送給master2,也就是maste1只存在一個binlog dump線程.。再由master2按照一主多從的架構推給其他的從庫。因爲會經歷兩次複製(master1->master2,master2->slave),所以效率也會差一下。可以將master2將表引擎設置爲BLACKHOLE。因爲master2並不承擔讀寫請求,只是做一箇中轉站的作用,所以推薦使用BLACKHOLE表引擎。(詳細內容可參考深入淺出MySQL一書)

3、雙主複製(有興趣可以參考有關書籍)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章