Mysql主從複製(重置版)

  MySQL Replication是Mysql自帶的一種功能,能夠實現將數據從一臺數據庫服務器(master)複製到一臺或多臺數據庫服務器(slave),默認狀況下屬於異步複製,無需維持長鏈接。經過配置能夠複製全部的庫或者其中幾個庫,又或者庫中的一部分表。
(1).工做原理
  簡單的說就是master服務器將數據庫的改變寫入二進制日誌(binary log),slave服務器同步這些二進制日誌事件(binary log events)到它的中繼日誌(relay log),而後slave服務器重作中繼日誌中的事件進行數據操做。
  注意:是由slave服務器開啓一個I/O線程拉取數據。單master對單slave狀況下slave服務器上壓力更大,但單master對多slave狀況下master服務器上壓力更大。
(2).做用
  1.故障切換
  2.備份服務,沒法對SQL語句執行產生的故障恢復,有限的備份
  3.高性能,能夠多臺slave,實現讀寫分離
(3).常見方案
  1.一主多從,一個master對應多個slave,I/O壓力集中在master上。
  2.M-S-S,中間那個S是slave中繼,爲了緩解master服務器的I/O壓力在中間加了一個slave中繼。
  3.M-M,雙主互備,互爲主從
  4.M-M-M,基本沒用
  5.一從多主,這是爲了節約成本,將多個master數據自動整合,但數據修改會很是多,從服務器壓力大。html

(4)主從複製時mysql配置文件會遇到的相關參數mysql

server-id = 1 數據庫的ID號,值必須爲1到2^32–1之間的一個正整數值,且惟一。master和slave都必須存在。
log-bin=mysql-bin 啓用並指定二進制日誌文件,能夠是相對路徑(基於datadir),也能夠是絕對路徑。master必須存在,slave能夠存在。
relay_log=mysql-relay-bin 啓用並指定中繼日誌,能夠是相對路徑(基於datadir),也能夠是絕對路徑。slave參數。
log-slave-updates=1 將複製事件寫入本身的二進制日誌。slave參數。
read_only=1 數據庫只讀,slave參數,通常用於讀寫分離時使用。
sync-binlog=1 實時寫入二進制日誌文件與磁盤同步
binlog-format=[STATEMENT|ROW|MIXED] 三個值分別表明基於SQL語句複製(STATEMENT),基於行的複製(ROW),混合模式複製(MIXED)。詳細查看:http://www.javashuo.com/article/p-buidscij-ba.html sql

 

若是如下兩個參數都沒指定,則slave默認複製全部數據庫
binlog-do-db=data 同步的二進制數據庫名,master參數
binlog-ignore-db=mysql 不一樣步的二進制數據庫名,master參數數據庫

 

explicit_defaults_for_timestamp=true 這是爲了取消TIMESTAMP字符類型(時間戳)隨更新而自動更新的操做(必須在建立timestamp字符類型前寫入配置文件,不然須要修改列參數),默認是off,沒用到TIMESTAMP字符類型不用設置。explicit_defaults_for_timestamp參數詳細查看:http://www.javashuo.com/article/p-orfwkmfp-k.htmlvim

 

slave-skip-errors有四個可選值,off、all、ddl_exist_errors和錯誤代碼([list of error codes]),默認爲off
slave-skip-errors=1062,1053 跳過指定錯誤代碼的錯誤,繼續執行復制
slave-skip-errors=all 跳過全部錯誤
slave-skip-errors=ddl_exist_errors 這是一系列錯誤代碼:1007,1008,1050,1051,1054,1060,1061,1068,1094,1146
說明:
  1007:數據庫已存在,建立數據庫失敗
  1008:數據庫不存在,刪除數據庫失敗
  1050:數據表已存在,建立數據表失敗
  1050:數據表不存在,刪除數據表失敗
  1054:字段不存在,或程序文件跟數據庫有衝突
  1060:字段重複,致使沒法插入
  1061:重複鍵名
  1068:定義了多個主鍵
  1094:位置線程ID
  1146:數據表缺失,請恢復數據庫服務器

(4).部署M-S(一主一從)異步

實驗環境:youxi1  192.168.5.101  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Master
     youxi2  192.168.5.102  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Slavetcp

1)master服務器上的操做ide

  建立一個用於複製所需的用戶性能

mysql> grant replication slave on *.* to repl@192.168.5.102 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;  //刷新權限表

  建立一個用於複製的數據庫

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,在[mysqld]模塊下操做。而後重啓mysqld

[root@youxi1 ~]# vim /etc/my.cnf
server-id=1  //添加或修改
log-bin=mysql-bin-master
binlog-do-db=test_db
slave-skip-errors=all  //我的建議跳過錯誤,這樣slave就不會運行這些錯誤語句 [root@youxi1 ~]# systemctl restart mysqld

  查看master狀態,記錄當前日誌文件名和當前節點。

mysql> show master status\G  //這是查看master的狀態
*************************** 1. row ***************************
             File: mysql-bin-master.000001  //當前日誌文件
         Position: 154  //當前節點
     Binlog_Do_DB: test_db  //同步的數據庫
 Binlog_Ignore_DB:   //不一樣步的數據庫
Executed_Gtid_Set: 
1 row in set (0.00 sec)

mysql> show binlog events\G  //這是查看二進制日誌信息
*************************** 1. row ***************************
   Log_name: mysql-bin-master.000001  //日誌文件名
        Pos: 4  //開始節點
 Event_type: Format_desc  //事件類型
  Server_id: 1  //執行服務器標識
End_log_pos: 123  //結束節點
       Info: Server ver: 5.7.16-log, Binlog ver: 4  //信息,更多的是執行的SQL語句
*************************** 2. row ***************************
   Log_name: mysql-bin-master.000001
        Pos: 123
 Event_type: Previous_gtids
  Server_id: 1
End_log_pos: 154
       Info: 
2 rows in set (0.00 sec)

說明:show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
    IN 'log_name' 指定要查詢的binlog文件名(不指定就是第一個binlog文件)
    FROM pos 指定從哪一個pos起始點開始查起(不指定就是從整個文件首個pos點開始算)
    LIMIT [offset,] 偏移量(不指定就是0)
    row_count 查詢總條數(不指定就是全部行)

  注意:若是防火牆是打開的,記得添加mysql的端口號。

[root@youxi1 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi1 ~]# firewall-cmd --reload 
success
[root@youxi1 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

 2)slave服務器上的操做

  master和slave必須保證數據庫版本一致,複製的數據庫在二進制日誌記錄操做前如出一轍。

  創建與master須要複製的如出一轍的數據庫,能夠從master導出再導入到slave,也能夠手動建立。

mysql> create database test_db;
Query OK, 1 row affected (0.01 sec)

  修改配置文件,在[mysqld]模塊下操做。而後重啓mysqld。

[root@youxi2 ~]# vim /etc/my.cnf
server-id=2    //若是沒有更多的需求(例如M-S-S,M-M,讀寫分離,MHA等),這樣就能夠了
[root@youxi2 ~]# systemctl restart mysqld

  指定master的配置信息

mysql> stop slave;  //若是是第一次配置slave,能夠不須要
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to master_host='192.168.5.101',  //master的IP地址
    -> master_port=3306,   //端口號,默認3306
    -> master_user='repl',  //用戶名
    -> master_password='12345678',  //密碼
    -> master_log_file='mysql-bin-master.000001',  //從哪一個二進制日誌文件讀取
    -> master_log_pos=154;  //從二進制日誌文件的哪一個pos點開始讀取
Query OK, 0 rows affected, 2 warnings (0.06 sec)
//若是沒有master_log_file和master_log_pos則默認從第一個二進制日誌文件的0pos點開始
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

  注意:若是在出錯後從新配置master信息,這時master的IP地址、端口號、用戶名、密碼沒有改變能夠不用從新配置,只需指定master_log_file和master_log_pos便可。

  查看slave的狀態

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.101
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-master.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: youxi2-relay-bin.000003
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-master.000001
             Slave_IO_Running: Yes  //這兩行都是Yes時就是配置正確了
            Slave_SQL_Running: Yes

3)測試

  在master上建立表,並添加數據

mysql> use test_db;
Database changed
mysql> create table user_id(id int,name varchar(20));
Query OK, 0 rows affected (0.05 sec)

mysql> insert into user_id values(1,'zhangsan');
Query OK, 1 row affected (0.02 sec)

  在slave上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

(5).部署M-M

  M-M其實就是基於M-S再作一個反向主從。我就接着上面的M-S往下作了

1)在youxi2(原salve)上操做

  建立複製用戶

mysql> grant replication slave on *.* to repl@192.168.5.101 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;      
Query OK, 0 rows affected (0.00 sec)

  修改配置文件,在[mysqld]模塊下操做。而後重啓mysqld。

[root@youxi2 ~]# vim /etc/my.cnf
log-bin=mysql-bin-slave  //添加或修改
binlog-do-db=test_db
[root@youxi2 ~]# systemctl restart mysqld

  查看master狀態

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-slave.000001
         Position: 154
     Binlog_Do_DB: test_db
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

  注意:若是防火牆是打開的,記得添加mysql的端口號。

[root@youxi2 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi2 ~]# firewall-cmd --reload 
success
[root@youxi2 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

2)在youxi1(原master)上操做

  指定master配置信息

mysql> stop slave;  //若是第一次配置slave,能夠不須要
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to master_host='192.168.5.102',master_user='repl',master_password='12345678',master_log_file='mysql-bin-slave.000001',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

  查看slave狀態

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-slave.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: youxi1-relay-bin.000002
                Relay_Log_Pos: 326
        Relay_Master_Log_File: mysql-bin-slave.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

3)測試

  在youxi2上插入數據

mysql> use test_db;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into user_id values(2,'lisi');
Query OK, 1 row affected (0.01 sec)

  在youxi1上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    2 | lisi     |
+------+----------+
2 rows in set (0.01 sec)

(6).部署M-S-S

實驗環境:youxi1  192.168.5.101  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Master
     youxi2  192.168.5.102  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Slave中繼
     youxi3  192.168.5.103  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Slave

1)master服務器上的操做

  建立一個用於複製所需的用戶

mysql> grant replication slave on *.* to repl@192.168.5.102 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;  //刷新權限表

  建立一個用於複製的數據庫

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,在[mysqld]模塊下操做。而後重啓mysqld

[root@youxi1 ~]# vim /etc/my.cnf
server-id=1
log-bin=mysql-bin-master
binlog-do-db=test_db
sync-binlog=1
binlog-format=row
[root@youxi1 ~]# systemctl restart mysqld

  查看master狀態,記錄當前日誌文件名和當前節點

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-master.000001
         Position: 154
     Binlog_Do_DB: test_db
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

mysql> show binlog events\G
*************************** 1. row ***************************
   Log_name: mysql-bin-master.000001
        Pos: 4
 Event_type: Format_desc
  Server_id: 1
End_log_pos: 123
       Info: Server ver: 5.7.16-log, Binlog ver: 4
*************************** 2. row ***************************
   Log_name: mysql-bin-master.000001
        Pos: 123
 Event_type: Previous_gtids
  Server_id: 1
End_log_pos: 154
       Info: 
2 rows in set (0.01 sec)

  注意:若是防火牆是打開的,記得添加mysql的端口號。

[root@youxi1 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi1 ~]# firewall-cmd --reload 
success
[root@youxi1 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

2)在slave中繼服務器上的操做

  slave中繼服務器是master服務器的從服務器,也是slave服務器的主服務器,因此其自己便是從,又是主。

  建立一個用於複製的用戶

mysql> grant replication slave on *.* to repl@192.168.5.103 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> flush privileges;  //刷新權限表
Query OK, 0 rows affected (0.01 sec)

  創建與master服務器相同的數據庫,能夠從master導出再導入到slave,也能夠手動建立。

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,由於是slave中繼服務器,自己並不會產生數據,因此二進制日誌文件裏都是從master服務器上拉取的事件,也就沒有指定同步或不一樣步的數據庫。

[root@youxi2 ~]# vim /etc/my.cnf
server-id=2
log-bin=mysql-bin-slave1  //開啓二進制日誌文件
log-slave-updates=1  //複製事件寫入到二進制日誌文件
binlog-format=row
[root@youxi2 ~]# systemctl restart mysqld

  指定master的配置信息

mysql> stop slave;  //若是是第一次配置slave,能夠不須要
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to master_host='192.168.5.101',  //master的IP地址
    -> master_user='repl',  //用戶名
    -> master_password='12345678',  //密碼
    -> master_log_file='mysql-bin-master.000001',  //從哪一個二進制日誌文件讀取
    -> master_log_pos=154;  //從二進制日誌文件的哪一個pos點開始讀取
Query OK, 0 rows affected, 2 warnings (0.06 sec)
//若是沒有master_log_file和master_log_pos則默認從第一個二進制日誌文件的0pos點開始
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

  查看master狀態,記錄當前日誌文件名和當前節點

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-slave1.000001
         Position: 322
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

  查看slave狀態

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.101
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-master.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: youxi2-relay-bin.000002
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-master.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

  注意:若是防火牆是打開的,記得添加mysql的端口號。

[root@youxi2 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi2 ~]# firewall-cmd --reload 
success
[root@youxi2 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

3)配置slave服務器

  建立和master同樣的數據庫,能夠從master導出再導入到slave,也能夠手動建立。

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,在[mysqld]模塊下操做。而後重啓mysqld。

[root@youxi3 ~]# vim /etc/my.cnf
server-id = 3
binlog-format=row
[root@youxi3 ~]# systemctl restart mysqld

  指定master的配置信息

mysql> stop slave;  //若是是第一次配置slave,能夠不須要
Query OK, 0 rows affected, 1 warning (0.00 sec)
 
mysql> change master to master_host='192.168.5.102',  //master的IP地址
    -> master_user='repl',  //用戶名
    -> master_password='12345678',  //密碼
    -> master_log_file='mysql-bin-slave1.000001',  //從哪一個二進制日誌文件讀取
    -> master_log_pos=322;  //從二進制日誌文件的哪一個pos點開始讀取
Query OK, 0 rows affected, 2 warnings (0.06 sec)
//若是沒有master_log_file和master_log_pos則默認從第一個二進制日誌文件的0pos點開始
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

  查看slave的狀態

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-slave1.000001
          Read_Master_Log_Pos: 322
               Relay_Log_File: youxi3-relay-bin.000005
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-slave1.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

4)測試

  在master服務器上建立表,並添加數據

mysql>  use test_db;
Database changed
mysql> create table user_id(id int,name varchar(20));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into user_id values(1,'zhangsan');
Query OK, 1 row affected (0.05 sec)

  在slave中繼服務器上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

  在slave服務器上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

5)若是不想slave中繼服務器同步數據,但又不影響slave服務器該怎麼作

  首先修改slave中繼服務器上表的引擎爲黑洞引擎

mysql> set sql_log_bin=off;  //關閉二進制日誌
Query OK, 0 rows affected (0.00 sec)

mysql> alter table test_db.user_id ENGINE=blackhole;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> set sql_log_bin=on;  //打開二進制日誌
Query OK, 0 rows affected (0.00 sec)

  而後查看下slave服務器的slave狀態

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-slave1.000001
          Read_Master_Log_Pos: 776
               Relay_Log_File: youxi3-relay-bin.000006
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-slave1.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

  再到master服務器上插入數據測試

mysql> insert into user_id values(2,'lisi');
Query OK, 1 row affected (0.02 sec)

  查看slave中繼服務器的數據

mysql> select * from test_db.user_id;
Empty set (0.00 sec)

  查看slave服務器數據

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    2 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

(7).擴展:mysql的1593報錯

  在作主從複製時,因爲我是克隆的服務器,致使了mysql的uuid相同,因此出現了1593報錯。

  當出現1593報錯時,使用SHOW VARIABLES LIKE '%server_%';查看兩個mysql的id和uuid。若是是server_id相同,進入/etc/my.cnf修改server_id的值。若是是server_uuid相同,使用SELECT uuid();隨機獲取一個uuid,而後進入$datadir/auto.cnf修改uuid的值。最後都須要重啓mysqld。

相關文章
相關標籤/搜索