上篇文章詳細介紹了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的主從複製介紹完畢,主從複製是一塊很大的內容,包括延遲排查,數據一致問題、快速主從搭建及主從複製的高可用,後面會繼續寫文章介紹,歡迎轉發評論!
後續文章將更新在我的小站上,歡迎查看。