MySQL主主復制及相關的排坑
主主復制的本質就是2臺MySQL服務器互為主從。
但如此配置極易產生問題,如數據不一致導致主鍵的沖突,以及一些其他的錯誤。
為了減少主鍵沖突的情況,可以考慮讓兩個節點的id分別使用技術和偶數,這就需要用到兩個服務器選項來配置。
auto_increment_offset #設置id的開始點
auto_increment_increment #設置id的步進
主主復制工作中不推薦使用,如確實需要使用,也將其當為主從來使用。
主主復制的搭建
使用2臺主機來配置主主復制
主機 | ip |
---|---|
Master1 | 192.168.73.110 |
Master2 | 192.168.73.111 |
配置Master1
1.修改配置文件
[[email protected] ~]# vim /etc/my.cnf
[mysqld]
log-bin
server-id=1
auto_increment_offset=1
auto_increment_increment=2
2.啟動MySQL服務
[[email protected] ~]# systemctl start mariadb
3.查看二進制日誌位置
[[email protected] ~]# mysql -e "SHOW MASTER LOGS;" +--------------------+-----------+ | Log_name | File_size | +--------------------+-----------+ | mariadb-bin.000001 | 245 | +--------------------+-----------+
4.創建一個用來復制數據的用戶
[[email protected] ~]# mysql -e "GRANT REPLICATION SLAVE ON *.* TO ‘repluser‘@‘192.168.73.%‘ IDENTIFIED BY ‘centos‘;"
配置Master2為Master1的從節點
1.修改配置文件
[[email protected] ~]# vim /etc/my.cnf
[mysqld]
log-bin
server-id=2
auto_increment_offset=1
auto_increment_increment=2
2.設置CHANGE MASTER TO
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST=‘192.168.73.110‘, MASTER_USER=‘repluser‘,MASTER_PASSWORD=‘centos‘,MASTER_PORT=3306,MASTER_LOG_FILE=‘mariadb-bin.000001‘,MASTER_LOG_POS=245;
Query OK, 0 rows affected (0.01 sec)
3.查看從節點狀態,確認無誤
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.73.110
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
4.啟動線程
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.01 sec)
5.再次查看從節點狀態
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.73.110
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 407
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 693
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes #線程已經全部啟動
6.查看二進制日誌位置
查看二級制日誌位置用於,給Master1作為從節點使用。由於Master2上無數據二進制日誌為幹凈日誌,所以可以直接供Master1使用。
MariaDB [(none)]> SHOW MASTER LOGS;
+--------------------+-----------+
| Log_name | File_size |
+--------------------+-----------+
| mariadb-bin.000001 | 245 |
+--------------------+-----------+
1 row in set (0.00 sec)
配置Master1為Master2的從節點
1.輸入CHANGE MASTER TO的信息
CHANGE MASTER TO MASTER_HOST=‘192.168.73.111‘, MASTER_USER=‘repluser‘,MASTER_PASSWORD=‘centos‘,MASTER_PORT=3306,MASTER_LOG_FILE=‘mariadb-bin.000001‘,MASTER_LOG_POS=245;
2.查看從狀態,確認信息無誤
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.73.111
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
3.啟動線程
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.01 sec)
4.再次查看slave status
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.73.111
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 245
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 531
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
主主復制搭建完畢
測試
測試一、查看Master1輸入數據,Master2能否復制
1.從Master1上導入hellodb數據庫
[[email protected] ~]# mysql -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
[[email protected] ~]# mysql < hellodb_innodb.sql
[[email protected] ~]# mysql -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| hellodb |
| mysql |
| performance_schema |
| test |
+--------------------+
2.從節點上查看數據庫
[[email protected] ~]# mysql -e "SHOW DATABASES;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| hellodb |
| mysql |
| performance_schema |
| test |
+--------------------+
測試二、Master2插入數據查看Master1是否能復制
1.在Master2中插入條記錄
[[email protected] ~]# mysql -e "INSERT hellodb.teachers(name,age) VALUE (‘Ye Fan‘,‘25‘);"
[[email protected] ~]# mysql -e "INSERT hellodb.teachers(name,age) VALUE (‘Shi Hao‘,‘20‘);"
[[email protected] ~]# mysql -e "SELECT * FROM hellodb.teachers"
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | Ye Fan | 25 | NULL |
| 7 | Shi Hao | 20 | NULL | #此處可以看到插入數據時主鍵tid是以2為步進遞增的。
+-----+---------------+-----+--------+
2.在Master1上查看數據
[[email protected] ~]# mysql -e "SELECT * FROM hellodb.teachers;"
+-----+---------------+-----+--------+
| TID | Name | Age | Gender |
+-----+---------------+-----+--------+
| 1 | Song Jiang | 45 | M |
| 2 | Zhang Sanfeng | 94 | M |
| 3 | Miejue Shitai | 77 | F |
| 4 | Lin Chaoying | 93 | F |
| 5 | Ye Fan | 25 | NULL |
| 7 | Shi Hao | 20 | NULL |
+-----+---------------+-----+--------+
測試三、兩邊同時創建一張相同的表
1.同時對兩個主機做出創建表的操作
2.查看Master1的hellodb庫
[[email protected] ~]# mysql -e "SHOW TABLES FROM hellodb"
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| test |
| toc |
+-------------------+
3.查看Master2的hellodb庫
[[email protected] ~]# mysql -e "SHOW TABLES FROM hellodb"
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| test |
| toc |
+-------------------+
此處看上好像沒問提
測試四、繼續插入數據,從看看復制狀況
1.在Master1上繼續往hellodb.test表中插入數據
[[email protected] ~]# mysql -e "INSERT hellodb.test VALUE(1,‘Tang San‘);"
2.Master2上查看復制狀況
[[email protected] ~]# mysql
MariaDB [(none)]> SELECT * FROM hellodb.test;
Empty set (0.00 sec)
#沒有復制到數據
查錯
分別查看Master1和Master2主機上的SLAVE STATUS;
Master1狀態
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.73.111
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 871
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 1018
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1050
Last_Error: Error ‘Table ‘test‘ already exists‘ on query. Default database: ‘‘. Query: ‘CREATE TABLE hellodb.test(id int auto_increment primary key,name char(20))‘
Skip_Counter: 0
Exec_Master_Log_Pos: 732
Relay_Log_Space: 1453
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1050
Last_SQL_Error: Error ‘Table ‘test‘ already exists‘ on query. Default database: ‘‘. Query: ‘CREATE TABLE hellodb.test(id int auto_increment primary key,name char(20))‘
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
1 row in set (0.00 sec)
ERROR: No query specified
Master2狀態
MariaDB [(none)]> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.73.110
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 8360
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 8308
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1050
Last_Error: Error ‘Table ‘test‘ already exists‘ on query. Default database: ‘‘. Query: ‘CREATE TABLE hellodb.test(id int auto_increment primary key,name char(20))‘
Skip_Counter: 0
Exec_Master_Log_Pos: 8022
Relay_Log_Space: 8942
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1050
Last_SQL_Error: Error ‘Table ‘test‘ already exists‘ on query. Default database: ‘‘. Query: ‘CREATE TABLE hellodb.test(id int auto_increment primary key,name char(20))‘
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1 row in set (0.00 sec)
ERROR: No query specified
顯示出來剛在在創建表時已經復制出錯,由於兩邊同時創建了同一張表發生了沖突
排錯
分別在主從節點上停止線程
MariaDB [(none)]> STOP SLAVE;
分別在主從節點上使用sql_slave_skip_counter忽略錯誤
MariaDB [(none)]> SET GLOBAL sql_slave_skip_counter=1;
分別在主從節點上再次啟動線程
MariaDB [(none)]> START SLAVE;
再次在從節點上查test表
[[email protected] ~]# mysql -e "SELECT * FROM hellodb.test;"
+----+----------+
| id | name |
+----+----------+
| 1 | Tang San |
+----+----------+
此時數據已經能正常復制過去
MySQL主主復制及相關的排坑