【20181204】 MySQL 雙主復制是如何避免回環復制的
阿新 • • 發佈:2018-12-04
nor *** read mysql 5.6 insert 會有 復制 數據 一模一樣 問題原因
想要了解這個問題的原因在於有一次面試的時候,面試官問我一個問題,就是MySQL的雙主復制的時候是如何避免回環復制這個問題的,說老實話在基於GTID復制的時候我還是比較了解的,因為GTID復制是MySQL本身是不會執行已經執行過的GTID事務,即使MySQL本身並不會執行已經執行過的GTID事務,但是還是會形成一個回環復制。那麽MySQL到底是如何解決回環復制的呢?
猜想
- 在我們搭建主從的時候我們可以清楚的知道,要想成功的搭建主從,那麽主從的server_id必須不能一模一樣的,所以猜想可能是因為server_id的原因。
- 在MySQL 5.5以及一切,我們搭建一主多從的時候,假如slave使用了相同的server_id就會發現在master和slave上面發現slave會經常的斷開重連,這個是因為slave在註冊的時候會去比對server_id,假如server_id存在的話則會有一個刪除操作,但是MySQL 5.6的版本以後引入了uuid,它會優先去比對uuid,假如不存在的話則會去比對server_id。所以在MySQL5.6以及以後是因為uuid的原因呢。
實驗
A. 搭建雙主。非gtid模式(具體過程不在描述)
master 1
........ ........ Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 2175 Relay_Log_File: rep_relay_log.000004 Relay_Log_Pos: 283 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes ........
master 2
Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 3385 Relay_Log_File: rep_relay_log.000004 Relay_Log_Pos: 1235 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes
B . master 1 上面執行創建表語句
mysql> show create table test \G
*************************** 1. row ***************************
Table: test
Create Table: CREATE TABLE `test` (
`class_num` int(11) NOT NULL AUTO_INCREMENT,
`class_name` varchar(25) DEFAULT NULL,
PRIMARY KEY (`class_num`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
C. master 1和2上面分別插入部分數據進行驗證。
+-----------+------------+
| class_num | class_name |
+-----------+------------+
| 4 | 物理 |
| 5 | 化學 |
| 6 | 生物 |
| 7 | 體育 |
| 8 | 123 |
+-----------+------------+
D. master 1 上面執行
mysql> stop slave;
mysql> set global server_id=3306;
mysql> start slave;
E. master 2上面執行
mysql> stop slave;
mysql> set global server_id=3307;
mysql> start slave;
F. master 1 上面執行
mysql> insert into test(class_name) values(‘321‘);
G. master 1上面觀察
mysql > show slave status;
......
Last_SQL_Error: Error ‘Duplicate entry ‘9‘ for key ‘PRIMARY‘‘ on query. Default database: ‘test‘. Query: ‘insert into test(class_name) values(‘321‘)‘
Replicate_Ignore_Server_Ids:
......
H. master 1上面執行下面命令,你會發現還是會有這個錯誤。
mysql> delete from test where class_num=9;
mysql> start slave;
mysql> show slave status;
......
Last_SQL_Error: Error ‘Duplicate entry ‘9‘ for key ‘PRIMARY‘‘ on query. Default database: ‘test‘. Query: ‘insert into test(class_name) values(‘321‘)‘
......
I. 解析binlog日誌信息:
#181204 16:15:00 server id 3306 end_log_pos 2762 CRC32 0xad6f9e83 Intvar
SET INSERT_ID=9/*!*/;
#181204 16:15:00 server id 3306 end_log_pos 2878 CRC32 0x5cf6d5f2 Query thread
_id=54 exec_time=124 error_code=0
SET TIMESTAMP=1543911300/*!*/;
insert into test(class_name) values(‘321‘)
/*!*/;
# at 2878
#181204 16:15:00 server id 3306 end_log_pos 2909 CRC32 0x9ccd43ee Xid = 139
COMMIT/*!*/;
# at 2909
#181204 16:30:52 server id 52213306 end_log_pos 2988 CRC32 0xc9831ff7 Query thread
_id=54 exec_time=0 error_code=0
SET TIMESTAMP=1543912252/*!*/;
BEGIN
/*!*/;
# at 2988
#181204 16:30:52 server id 52213306 end_log_pos 3096 CRC32 0x37f9c65e Query thread
_id=54 exec_time=0 error_code=0
SET TIMESTAMP=1543912252/*!*/;
delete from test where class_num=9
/*!*/;
# at 3096
#181204 16:30:52 server id 52213306 end_log_pos 3127 CRC32 0xc68f6eae Xid = 151
COMMIT/*!*/;
# at 3127
#181204 16:15:00 server id 3306 end_log_pos 3206 CRC32 0xd5fc40b3 Query thread
_id=54 exec_time=959 error_code=0
SET TIMESTAMP=1543911300/*!*/;
BEGIN
/*!*/;
# at 3206
# at 3238
#181204 16:15:00 server id 3306 end_log_pos 3238 CRC32 0x52663932 Intvar
SET INSERT_ID=9/*!*/;
#181204 16:15:00 server id 3306 end_log_pos 3354 CRC32 0xc642ad10 Query thread
_id=54 exec_time=959 error_code=0
SET TIMESTAMP=1543911300/*!*/;
insert into test(class_name) values(‘321‘)
/*!*/;
# at 3354
#181204 16:15:00 server id 3306 end_log_pos 3385 CRC32 0xd5e2ad2a Xid = 155
COMMIT/*!*/;
DELIMITER ;
# End of log file
可以明顯得看得到 insert into test(class_name) values(‘321‘);
這條SQL執行了好多次,這個時候明顯可以驗證在非GTID復制得情況下面是由於server_id才避免了回環復制。
結論
在進行修改uuid得時候發現這是一個只讀參數,不能在修改。並且uuid是MySQL初始化得時候先去auto.cnf文件裏面查找,若不存在則會隨機生成一串隨機碼,所以可以直接去除這個。再上面得實驗中可以獲取得到MySQL再非GTID下面是由server_id得原因才避免了回環復制的,但是GTID環境下面會不會也是因為server_id的原因呢,暫時就沒有去驗證了。不過我還是認為gtid下面也是因為GTID的原因。
【20181204】 MySQL 雙主復制是如何避免回環復制的