MySQL 主從復(fù)制中創(chuàng)建復(fù)制用戶的時機(jī)探討
背景
該問題來自某客戶,據(jù)描述,他們在部署 MySQL 主從復(fù)制時,有時候僅在主庫上創(chuàng)建復(fù)制用戶,有時候主從實例上都會去分別創(chuàng)建復(fù)制用戶,發(fā)現(xiàn)這兩種方式都可以成功建立復(fù)制。針對這一現(xiàn)象,進(jìn)行了一輪驗證,來觀察采用不同方式創(chuàng)建復(fù)制用戶對主從復(fù)制的影響。
通常來說,用得較多的方式是在搭建主從復(fù)制前,先在主庫創(chuàng)建好復(fù)制用戶,然后做一個 Xtrabackup 物理全備,再拿到從庫上恢復(fù)并搭建主從。除此以外,還有哪些方式呢?分別對主從復(fù)制有哪些影響?一起來看一下。
驗證
- MySQL 版本為 5.7.32,主庫:10.186.60.62,從庫:10.186.60.68。
 - 為了演示方便,本次搭建主從復(fù)制時均采用 mysqldump 進(jìn)行邏輯備份。
 
場景 1:僅在主庫創(chuàng)建復(fù)制用戶
1.主庫做一個備份并拷貝到從庫
- /usr/local/mysql5732/bin/mysqldump --single-transaction --master-data=2 -B zlm -S /tmp/mysql3332.sock -p > zlm.sql
 - scp zlm.sql root@10.186.60.68:~
 
2.登陸從庫執(zhí)行導(dǎo)入
- mysql> source zlm.sql
 
由于沒有使用參數(shù) --set-gtid-purged=off,導(dǎo)出的語句中會帶有 SET @@GLOBAL.GTID_PURGED='xxxx:1-xx' 并執(zhí)行,導(dǎo)入前需要先在從庫上執(zhí)行 reset master。
3.主庫創(chuàng)建復(fù)制用戶
- mysql> create user repl1 identified by 'repl1';
 
4.從庫配置主從復(fù)制并啟動
- mysql> change master to master_host='10.186.60.62',master_port=3332,master_user='repl1',master_password='repl1',master_auto_position=1;
 - mysql> start slave;
 

啟動復(fù)制后,報了 Error 1045 的錯誤,此處并不是密碼錯,而是沒有給復(fù)制用戶配置 replication slave 權(quán)限,在主庫上對 repl1 用戶執(zhí)行賦權(quán)后(grant replication slave on *.* to repl1;),再啟動復(fù)制就正常了。
主從復(fù)制正常以后,也會在從庫上創(chuàng)建復(fù)制用戶 repl1。

從庫上并沒有創(chuàng)建過復(fù)制用戶 repl1,主從復(fù)制就正常搭建好了,為什么呢?因為 change master to 語句中指定的 master_user 是主庫上的復(fù)制用戶,從庫通過這個用戶連接到主庫進(jìn)行同步,當(dāng)開啟復(fù)制線程后,主庫上創(chuàng)建復(fù)制用戶的語句會在從庫上進(jìn)行回放,于是從庫上也會有這個復(fù)制用戶了。
結(jié)論 1
- 搭建主從復(fù)制時,在從庫創(chuàng)建復(fù)制用戶不是必須的,僅在主庫創(chuàng)建即可,復(fù)制用戶會同步到從庫。
 
場景 2:主從庫單獨(dú)創(chuàng)建復(fù)制用戶(create 語句)
1.主庫做一個備份并拷貝到從庫(gtid_purged=xxxx:1-23)
2.從庫執(zhí)行導(dǎo)入
3.主庫創(chuàng)建復(fù)制用戶并賦權(quán)
- mysql> create user repl2 identified by 'repl2';
 - mysql> grant replication slave on *.* to repl2;
 

4.從庫創(chuàng)建復(fù)制用戶

由于不想在從庫上產(chǎn)生由從庫 uuid 寫入的 binlog 事務(wù),此處設(shè)置了 sql_log_bin=0,使事務(wù)不被記錄到 binlog 中,原因是在數(shù)據(jù)庫管理平臺對高可用集群進(jìn)行管理時,通常是不允許從庫上有主庫不存在的 GTID 事務(wù)的。
5.從庫配置主從復(fù)制并啟動
- mysql> change master to master_host='10.186.60.62',master_port=3332,master_user='repl2',master_password='repl2',master_auto_position=1;
 - mysql> start slave;
 

由于從庫上已經(jīng)創(chuàng)建了復(fù)制用戶,當(dāng)回放到主庫的這個事務(wù)時會報 Error 1396 的錯誤。
可以用 create user 語句創(chuàng)建一個重復(fù)用戶來驗證。

解析主庫 binlog,啟動復(fù)制后執(zhí)行的第一個事務(wù)就是這個 24 的創(chuàng)建用戶語句。

結(jié)論 2
在從庫導(dǎo)入備份后并分別在主、從庫單獨(dú)創(chuàng)建復(fù)制用戶后,當(dāng)從庫執(zhí)行到創(chuàng)建用戶的事務(wù)時會導(dǎo)致復(fù)制中斷。
場景 3:主從庫單獨(dú)創(chuàng)建復(fù)制用戶(grant 語句)
1.主庫做一個備份并拷貝到從庫(gtid_purged=xxxx:1-28)
2.從庫執(zhí)行導(dǎo)入
3.主庫創(chuàng)建復(fù)制用戶
- mysql> grant replication slave on *.* repl3 identified by 'repl3';
 

4.從庫創(chuàng)建復(fù)制用戶

5.從庫配置主從復(fù)制并啟動
- mysql> change master to master_host='10.186.60.62',master_port=3332,master_user='repl2',master_password='repl2',master_auto_position=1;
 - mysql> start slave;
 

這次啟動復(fù)制后并沒有報錯。為何用 grant 語句創(chuàng)建用戶就可以,用 create 語句就不行呢?
create 與 grant 語句都會產(chǎn)生事務(wù)并記錄到 binlog 中,但區(qū)別是 grant 語句是一個近似冪等的操作,而 create 語句不是。
解析主庫 binlog,29 和 30 都是重復(fù)執(zhí)行 grant 的事務(wù)。

觀察 show slave stauts\G,從庫上也把 29,30 這兩個事務(wù)都回放掉了,重復(fù)執(zhí)行它們并不影響主從復(fù)制。

但要注意的是,在 MySQL 8.0 中已經(jīng)禁止通過 grant 這種語法來創(chuàng)建用戶了。

結(jié)論 3
- 從庫導(dǎo)入備份并在主從庫分別使用 grant 語句創(chuàng)建用戶后,在從庫回放時不會導(dǎo)致復(fù)制中斷。
 
總結(jié)
1.根據(jù)以上驗證結(jié)果得知,在搭建主從復(fù)制時,采用多種方式創(chuàng)建復(fù)制用戶都是可行的,但有些方式存在一些限制,如:在主、從實例上分別創(chuàng)建復(fù)制用戶。雖然執(zhí)行 grant 語句創(chuàng)建用戶不會導(dǎo)致復(fù)制中斷,但其并不是標(biāo)準(zhǔn)的 MySQL 創(chuàng)建用戶語法,在 MySQL 8.0 中已被視為語法錯誤,因此不推薦采用這樣的方式來搭建主從。
2.創(chuàng)建復(fù)制用戶的方式
Create 語句創(chuàng)建用戶時
1.主庫創(chuàng)建完復(fù)制用戶后做備份,再配置主從
2.備份后僅在主庫創(chuàng)建復(fù)制用戶,再配置主從(推薦)
3.如果要在主、從庫分別創(chuàng)建復(fù)制用戶,應(yīng)先設(shè)置 session 級別的 sql_log_bin=0,再配置主從
Grant 語句創(chuàng)建用戶時(MySQL 5.7 及以下版本)
1.主庫先創(chuàng)建復(fù)制用戶后備份,再配置主從
2.僅在主庫創(chuàng)建復(fù)制用戶,再配置主從(推薦)
3.主、從庫分別創(chuàng)建復(fù)制用戶,再配置主從















 
 
 
















 
 
 
 