MySQL數據庫運維之主從複製搭建

上篇文章詳細介紹了MySQL數據庫的單機多實例搭建,本篇文章將在上篇文章的基礎上介紹MySQL主從複製過程,其中常見的複製架構有:異步複製,半同步複製及同步複製。經常使用的複製架構有異步複製及半同步複製!

1、常見的複製架構mysql

一、主主複製
(1)結構圖:sql

圖片描述

(2)說明:主主複製即複製的兩個實例互爲主從,兩個庫中均可以同時讀和寫;
(3)優勢:數據庫

a、對於讀寫請求都較多的需求,能夠在多個實例之間分攤讀寫請求,減輕單實例的讀寫壓力
b、互爲主從,當一個示例出故障時,能夠迅速切換到另一個實例上,提供讀寫服務

二、一主一從
(1)結構圖:vim

圖片描述

(2)說明:指的是在兩個數據庫實例中,一個實例扮演着主庫的角色,另外一個實例扮演着從庫的角色。這種方案中,從庫一般用來做爲備份使用,提供服務的多爲主庫;
(3)優勢:安全

a、多數狀況下,能夠有效下降因某臺數據庫服務器故障而致使數據丟失的機率
b、做爲備份服務器,能夠在從庫上完成在線數據的全備份,而不影響主庫的寫服務

三、一主多從
(1)結構圖:服務器

圖片描述

(2)說明:指的是在多個數據庫實例中,只包含了一個主庫,其餘實例都做爲該主庫的從庫,這種架構是業務規模較大場景中的一種複製架構;
(3)優勢:網絡

a、該方已經比較成功,並且使用範圍極爲普遍,出問題以後能夠迅速找到解決方案
a、做爲主庫的備份,能夠迅速擴展多個從庫
b、可使用mysql-proxy等中間件提供讀寫分離服務,經過多個從庫來應對大量的讀請求,提升網站的吞吐量
c、當主庫出故障時,從庫能夠快速接管主庫,成爲新的主庫,提供寫服務

2、主從複製的原理和過程架構

一、主從異步複製的原理異步

主庫上的二進制bin-log中記錄主庫的全部DML操做,同時在主庫上運行有一個IO線程,用於響應從庫上的bin-log日誌讀取請求;在從庫上運行有一個IO線程和一個SQL線程,IO線程會實時經過網絡請求去從庫上讀取bin-log日誌,而後寫入到自身的relay-log日誌文件中,同時運行在從庫上的SQL線程會去解析並讀取relay-log,而後在自身庫上執行讀取到的SQL,完成主從數據的同步,示意圖以下:
圖片描述
二、主從同步的工做過程
(1)詳細過程socket

a、主庫上會開啓了二進制bin-log日誌記錄,同時運行有一個IO線程;
b、主庫上對於須要同步的數據庫或者表所發生的全部DML操做都會被記錄到bin-log二進制日誌文件中;
c、從庫上開啓relay-log日誌,同時運行有一個IO線程和一個SQL線程;
d、IO線程負責從主庫中讀取bin-log二進制日誌,並寫入到本地的relay-log日誌中,同時記錄從庫所讀取到的主庫的日誌文件位置信息,以便下次從這個位置點再次讀取;
e、SQL線程負責從本地的relay-log日誌中讀取同步到的二進制日誌,並解析爲數據庫能夠識別的SQL語句,而後應用到本地數據庫,完成同步;
f、執行完relay-log中的操做以後,進入睡眠狀態,等待主庫產生新的更新;

(2)以上詳細過程可總結爲三步

第一步:主庫在每一個事務更新數據完成以前,將該操做記錄串行地寫入到binlog文件中;
第二步:從庫開啓一個I/O線程,該線程對主庫打開一個普通鏈接,主要工做是讀取二進制日誌。若是讀取的進度已經跟上了主庫,就進入睡眠狀態並等待主庫產生新的事件。I/O線程最終的目的是將這些事件寫入到中繼日誌中;
第三步:SQL線程會讀取中繼日誌,並順序執行該日誌中的SQL事件,從而與主數據庫中的數據保持一致;

3、MySQL異步複製搭建過程(單機多實例介紹,沿用上篇文章中搭建的多實例環境)
一、環境準備

操做系統:CentOS6.9
服務器IP:192.168.0.10
數據庫版本:MySQL-5.6.39
數據庫實例:實例1--3306端口(主),實例2--3307端口(從)

二、編輯3306實例的配置文件,打開該實例的二進制日誌,並修改server-id,以下

[root@WB-BLOG ~]# cd /mysql_data/3306/
[root@WB-BLOG 3306]# vim my.cnf
    [mysqld]
    server_id=3
    log_bin=/mysql_data/3306/data/mysql-bin
    log_bin_index=/mysql_data/3306/data/mysql-bin-index
    binlog_format=mixed
    ...

參數解釋:

(1)server-id:用來標識一個惟一的實例,若是是在同一個局域網內,可使用ip地址的最後一段,要保證惟一
(2)log_bin:二進制日誌文件的路徑,mysql用戶對該路徑必須具備讀寫權限
(3)log_bin_index:二進制文件的索引路徑,mysql用戶對該路徑必須具備讀寫權限
(4)binlog_format:表示二進制日誌內容的記錄方式,有三種方式:
    a、row:基於行記錄的方式,MySQL會將真實發生變化的行記錄進日誌,因此若是有update更新全表的操做,二進制日誌文件會變得很是大。一般用於SQL語句複雜可是影響的行比較少的場景
    b、statement:基於語句的方式,MySQL會將致使數據發生變化的SQL語句記錄到日誌文件中,適用於一條語句影響不少行的場景,可是注意當在主庫上使用到了UUID,SYSDATE,FOUND_ROWS函數時,使用statement方式的複製會出現主從不一致的狀況;
    c、mixed:混合記錄模式,MySQL會自動進行判斷具體是使用row格式仍是statement格式,一般狀況下都使用mixed,由MySQL來進行判斷

三、重啓主庫

[root@WB-BLOG ~]# cd /mysql_data/3306/
[root@WB-BLOG 3306]# ./mysqld restart

四、備份主庫的數據

[root@WB-BLOG 3306]# cd /usr/local/mysql-5.6.39/bin/
[root@WB-BLOG tmp]# ./mysqldump -uroot -proot -h127.0.0.1 -P3306 -S /mysql_data/3306/data/mysql.sock -A --master-data=2 -F --single-transaction | gzip > /tmp/mysql_all.sql.gz

參數說明:

-S:指定socket文件,單機多實例必需要指定
-A:--all-databases,表示備份全部的數據庫
--master-data:表示change master命令是否包括在備份以後的sql文件中,經常使用的值有1和2
    1:表示change master指令在sql文件中處於打開狀態,可用於快速建立主從同步,不用再次手動修改日誌文件名稱和位置點
    2:表示change master指令在sql文件中會被註釋,從庫上使用change master時須要手動指定日誌文件的文件名和位置點
-F:表示備份日誌的時候刷新二進制日誌,從新建立一個新的二進制日誌文件
--single-transaction:用於InnoDB存儲引擎格式的表備份,導出開始時設置事務隔離狀態並使用一致性快照開始事務,然後立刻執行unlock tables,而後執行導出
gzip:表示將備份的sql文件壓縮
#其餘常見參數在後面的MySQL數據備份於恢復會詳細介紹

五、登錄主庫,而後建立複製帳戶

[root@WB-BLOG 3306]# cd ..
[root@WB-BLOG mysql_data]# ./mysql_login.sh

mysql-server-3306> USE mysql
#受權從庫的
mysql-server-3306> GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* to 'repl'@'127.0.0.1' IDENTIFIED BY 'repl';
mysql-server-3306> FLUSH PRIVILEGES;

六、查看主庫的二進制日誌文件及位置點

mysql-server-3306> show master status \G
*************************** 1. row ***************************
             File: mysql-bin.000014
         Position: 367
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

七、將主庫導出的數據導入從庫中

[root@WB-BLOG mysql_data]# cd /usr/local/mysql-5.6.39/bin/
[root@WB-BLOG bin]# gzip -d /tmp/mysql_all.sql.gz | ./mysql -uroot -proot -S /mysql_data/3307/data/mysql.sock

八、修改從庫的配置文件,開啓relay-log日誌,並設置server-id,以下

[mysqld]
server-id=4
relay_log=/mysql_data/3307/data/relay-log
relay_log_index = /mysql_data/3307/data/relay-log-index
...

九、修改從庫上的master指向,使其指向主庫,而且從主庫上最新的二進制日誌和位置點開始同步,而後啓動主從同步

[root@WB-BLOG mysql_data]# ./mysql_login.sh
mysql-server-3307> CHANGE MASTER TO master_host = '127.0.0.1',master_port = 3306,master_user='repl',master_password='repl',master_log_file='mysql-bin.000014',master_log_pos = 367; 
mysql-server-3307> START SLAVE;
mysql-server-3307> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000015
          Read_Master_Log_Pos: 425
               Relay_Log_File: relay-log.000004
                Relay_Log_Pos: 588
        Relay_Master_Log_File: mysql-bin.000015
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:

注意:上述結果中Slave_IO_Running和Slave_SQL_Running都爲Yes表示主從同步成功,若是爲Connecting...,能夠等待一會再次查看,若是爲No,表示同步失敗;
參數說明:

master_host:主庫的主機名或者IP地址
master_port:主庫的端口號,必須爲整數,不能加引號,不然會提示錯誤
master_user:在主庫上添加的複製用戶名稱
master_password:在主庫上添加的複製用戶密碼
master_log_file:主庫當前的二進制日誌文件名稱
master_log_pos:主庫當前的二進制文件位置點,整數,不可加引號,不然會提示錯誤

開啓主從的另一種方法是分別開啓SQL線程和IO線程,以下:

mysql> START SLAVE IO_THREAD;
mysql> START SLAVE SQL_THREAD;

十、驗證,登錄主庫,而後建立數據庫,查看從庫是否能夠正常同步

mysql-server-3306> CREATE DATABASE test_db;
mysql-server-3306> QUIT
mysql-server-3307> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| test_db            |
+--------------------+
5 rows in set (0.00 sec)
#從上面的結果能夠看到,test_db已經同步到3307實例上了

十一、至此,MySQL的主從複製搭建完畢。

十二、主從同步中常見的問題
(1)從庫的IO線程沒法鏈接,經過"show slave status G"能夠查看到具體的錯誤信息
緣由1:在主庫上建立的用戶受權錯誤,致使從庫沒法遠程鏈接主庫
解決辦法1:在主庫上經過"show grants for 'user'@'ip';"查看受權是否正確,若是錯誤,從新受權便可

緣由2:若是是獨立主機上的兩個主從數據庫實例,受權正確的狀況下,多是因爲主庫的防火牆攔截致使從庫沒法鏈接主庫
解決辦法2:關閉主庫的防火牆,或者在主庫所在服務器添加防火牆規則,容許從庫的tcp鏈接

(2)從庫啓動的時候提示server-id衝突,致使沒法同步主庫上的數據
緣由:主從庫配置文件中的server-id相同了
解決辦法:將主庫可從庫配置文件中的server-id改成不一樣,從新開啓從庫上的同步便可

(3)在從庫上執行了建立庫或者表的操做,而後在主庫上又執行了一遍,致使同步錯誤,以下:

Last_SQL_Error: Error 'Can't create database 'test1'; database exists' on query. Default database: 'test1'. Query: 'create database test1'

緣由:從庫上建立了庫,主庫上再次建立,從庫會將主庫上的建立過程再次應用到從庫,致使從庫上建立同名的庫,發生錯誤
解決辦法:中止從庫,而後設置sql_slave_skip_count,使其跳過同步主庫建立庫的操做,從下一個操做開始同步,以下:

#中止從庫
mysql-server-3307> STOP SLAVE;
Query OK, 0 rows affected (0.00 sec)
#向前跳躍一步,從下一個點開始同步
mysql-server-3307> SET GLOBAL sql_slave_skip_counter =1;
Query OK, 0 rows affected (0.00 sec)
#從新開啓從庫上的同步
mysql-server-3307> START SLAVE ;
Query OK, 0 rows affected (0.03 sec) 
#再次查看,發現已經正常

針對直接寫從庫的操做,能夠再從庫上建立一個普通用戶,授予其部分操做權限,而後設置從庫的只讀,經過在從庫的配置文件中增長"read-only"參數來設置。可是注意,這個參數對並且只對非super用戶生效,對root用戶沒有任何效果。

1三、再生產場景下如何保證主庫上的用戶能夠有寫權限,從庫上的用戶只有讀權限
方法1:在設置從庫同步的時候,排除對mysql系統庫的同步,經過在配置文件中指定binlog_ignore_db=mysql來排除不須要同步的庫,或者在配置文件中指定binlog_do_db=db_name只來同步須要同步的庫,而後分別在主庫上建立能夠寫的用戶,在從庫上建立只能讀的用戶;

[mysqld]
binlog_ignore_db=mysql
binlog_do_db=user_db

方法2:在未排除任何庫的狀況下,先在主庫上建立能夠讀寫的用戶,而後在從庫中重新回收用戶的寫權限;
方法3:在主庫和從庫上建立不一樣的用戶,而後分別授予不一樣的權限,使得主庫只能寫,從庫只能讀;

4、MySQL半同步搭建過程(介紹過程仍然使用單機多實例的環境)

一、定義
是介於異步複製和全同步複製之間的一種複製方式,主庫在執行完客戶端提交的事務後不是馬上返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。

二、優缺點
(1)優勢:有效的提升了數據的安全性,須要等到數據寫到從庫以後才返回給客戶端;
(2)缺點:由於須要等待至少一個從庫接收到並寫入relaylog中,索引會形成必定的網絡延遲,須要在網絡延遲較低的環境中使用

三、搭建過程
(1)前提條件:

a、MySQL數據庫版本爲5.5及以上
b、屬性變量have_dynamic_loading的值爲YES
c、異步複製已經搭建完成

(2)查看主庫和從庫上的have_dynamic_loading變量

[root@WB-BLOG mysql_data]# ./mysql_login.sh 
mysql-server-3306> SHOW VARIABLES LIKE 'have_dynamic_loading';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| have_dynamic_loading | YES   |
+----------------------+-------+
1 row in set (0.00 sec)

(3)登錄主庫,在主庫上安裝半同步插件

mysql-server-3306> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)
mysql-server-3306> SHOW PLUGINS \G
*************************** 43. row ***************************
   Name: rpl_semi_sync_master
 Status: ACTIVE
   Type: REPLICATION
Library: semisync_master.so
License: GPL
43 rows in set (0.00 sec)
#查看輸出結果中包括上面的一行,表示半同步插件安裝成功

注:若是想卸載半同步插件,可使用以下命令:

mysql-server-3306> UNINSTALL PLUGIN rpl_semi_sync_master;

(4)登錄從庫,安裝從庫上的半同步插件

mysql-server-3307> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)
mysql-server-3307> SHOW PLUGINS;
*************************** 43. row ***************************
   Name: rpl_semi_sync_slave
 Status: ACTIVE
   Type: REPLICATION
Library: semisync_slave.so
License: GPL
43 rows in set (0.01 sec)

注:從庫上的半同步插件,也可使用以下命令完成卸載:

mysql-server-3307> UNINSTALL PLUGIN rpl_semi_sync_slave;

(5)查看插件是否加載成功
主庫:

mysql-server-3306> SELECT plugin_name,plugin_status FROM information_schema.plugins WHERE plugin_name LIKE '%semi%';
+----------------------+---------------+
| plugin_name          | plugin_status |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+
1 row in set (0.00 sec)

從庫:

mysql-server-3307> SELECT plugin_name,plugin_status FROM information_schema.plugins WHERE plugin_name LIKE '%semi%';
+---------------------+---------------+
| plugin_name         | plugin_status |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE        |
+---------------------+---------------+
1 row in set (0.00 sec)

(6)配置並開啓主庫的半同步複製,而後重啓主庫

[root@WB-BLOG 3306]# vim my.cnf
#在mysqld段下面添加以下內容:
    [mysqld]
    plugin-load = rpl_semi_sync_master=semisync_master.so
    rpl_semi_sync_master_enabled=1
[root@WB-BLOG 3306]# ./mysqld restart

(7)配置並開啓從庫的半同步複製,而後重啓從庫

[root@WB-BLOG 3307]# vim my.cnf
#添加以下內容:
    [mysqld]
    plugin-load = rpl_semi_sync_slave=semisync_slave.so
    rpl_semi_sync_slave_enabled=1
[root@WB-BLOG 3307]# ./mysqld restart

(8)重啓從庫上的IO線程

mysql-server-3307> STOP SLAVE IO_THREAD;          
Query OK, 0 rows affected (0.00 sec)
ysql-server-3307> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

(9)查看主庫和從庫上的半同步複製是否在運行
登陸主庫查看:

mysql-server-3306> SHOW STATUS LIKE 'rpl_semi_sync_master_status';
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_status | ON    |
+-----------------------------+-------+

登陸從庫查看:

mysql-server-3307> SHOW STATUS LIKE 'rpl_semi_sync_slave_status';      
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

上述結果表示主庫和從庫上的半同步複製運行正常。

(10)驗證半同步複製是否正常
驗證方法:正常在主庫上建立一張表,會馬上返回,耗時0.1s。關閉從庫的io線程,而後在主庫上執行建表操做,會發現,主庫上回阻塞10秒以後纔會返回,而這個時間正好和主庫上的rpl_semi_sync_master_timeout相同,表示半同步起做用了,主庫的DDL操做須要等到從庫應用完relaylog以後才返回;

#主庫執行:
mysql-server-3307> STOP SLAVE IO_THREAD;

#從庫執行:
mysql-server-3306> CREATE TABLE test(id int);
Query OK, 0 rows affected (10.03 sec)

#查看主庫上的rpl_semi_sync_maser_timeout
mysql-server-3306> SHOW VARIABLES LIKE 'rpl_semi_sync_master_timeout';
+------------------------------+-------+
| Variable_name                | Value |
+------------------------------+-------+
| rpl_semi_sync_master_timeout | 10000 |
+------------------------------+-------+

至此,MySQL的半同步複製搭建完成。

四、半同步搭建中常見問題
(1)主從不能正常同步:和主從同步沒法正常複製的排查方法相同
(2)不能正常安裝半同步插件
緣由1:多是版本問題
解決辦法1:查看MySQL實例的版本,若是版本問題,更換新版本從新安裝便可

mysql> SELECT version();

緣由2:MySQL的安裝目錄中未包含用於半同步複製的共享庫
解決辦法2:找到該版本對應的半同步共享庫,而後從新安裝

5、全同步複製
同步複製在全部複製方案中最安全,可是性能最差,並且須要使用DRBD(分佈式複製塊設備)來完成數據的同步,DRBD是一種相似於"rsync+inotify"的架構,一般使用較少,幾乎不用,此處不作詳細介紹。

到此,MySQL的主從複製介紹完畢,主從複製是一塊很大的內容,包括延遲排查,數據一致問題、快速主從搭建及主從複製的高可用,後面會繼續寫文章介紹,歡迎轉發評論!

後續文章將更新在我的小站上,歡迎查看。

相關文章
相關標籤/搜索