【20181204】 MySQL 雙主複製是如何避免迴環複製的

問題緣由

想要了解這個問題的緣由在於有一次面試的時候,面試官問我一個問題,就是MySQL的雙主複製的時候是如何避免迴環複製這個問題的,說老實話在基於GTID複製的時候我仍是比較瞭解的,由於GTID複製是MySQL自己是不會執行已經執行過的GTID事務,即便MySQL自己並不會執行已經執行過的GTID事務,可是仍是會造成一個迴環複製。那麼MySQL究竟是如何解決迴環複製的呢?mysql

猜測

  1. 在咱們搭建主從的時候咱們能夠清楚的知道,要想成功的搭建主從,那麼主從的server_id必須不能如出一轍的,因此猜測多是由於server_id的緣由。
  2. 在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 2sql

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 上面執行建立表語句ide

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上面分別插入部分數據進行驗證。ui

+-----------+------------+
| 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上面執行code

mysql> stop slave;
mysql> set global server_id=3307;
mysql> start slave;

F. master 1 上面執行server

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上面執行下面命令,你會發現仍是會有這個錯誤。it

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的緣由。

相關文章
相關標籤/搜索