mysql5.5中的半同步複製

白及88發表於2016-03-04

先來看下MYSQL非同步複製的概念: 
  非同步複製:MySQL本身支援單向的、非同步的複製。非同步複製意味著在把資料從一臺機器拷貝到另一臺機器時有一個延時 – 最重要的是這意味著當應用系統的事務提交已經確認時資料並不能在同一時刻拷貝/應用到從機。通常這個延時是由網路頻寬、資源可用性和系統負載決定的。然而,使用正確的元件並且調優,複製能做到接近瞬時完成。 
  
   當主庫有更新的時候,主庫會把更新操作的SQL寫入二進位制日誌(Bin log),並維護一個二進位制日誌檔案的索引,以便於日誌檔案輪迴(Rotate)。在從庫啟動非同步複製的時候,從庫會開啟兩個I/O執行緒,其中一個執行緒連線主庫,要求主庫把二進位制日誌的變化部分傳給從庫,並把傳回的日誌寫入本地磁碟。另一個執行緒則負責讀取本地寫入的二進位制日誌,並在本地執行,以反映出這種變化。較老的版本在複製的時候只啟用一個I/O執行緒,實現這兩部分的功能。 

同步複製:同步複製可以定義為資料在同一時刻被提交到一臺或多臺機器,通常這是通過眾所周知的“兩階段提交”做到的。雖然這確實給你在多系統中保持一致性,但也由於增加了額外的訊息交換而造成效能下降。 

使用MyISAM或者InnoDB儲存引擎的MySQL本身並不支援同步複製,然而有些技術,例如分散式複製塊裝置(簡稱DRBD),可以在下層的檔案系統提供同步複製,允許第二個MySQL伺服器在主伺服器丟失的情況下接管(使用第二伺服器的複本)。要了解更多資訊, 

  MYSQL 5。5開始,支援半自動複製。之前版本的MySQL Replication都是非同步(asynchronous)的,主庫在執行完一些事務後,是不會管備庫的進度的。如果備庫不幸落後,而更不幸的是主庫此時又出現Crash(例如當機),這時備庫中的資料就是不完整的。簡而言之,在主庫發生故障的時候,我們無法使用備庫來繼續提供資料一致的服務了。 

Semisynchronous Replication則一定程度上保證提交的事務已經傳給了至少一個備庫。 
Semi synchronous中,僅僅保證事務的已經傳遞到備庫上,但是並不確保已經在備庫上執行完成了。 

此外,還有一種情況會導致主備資料不一致。在某個session中,主庫上提交一個事務後,會等待事務傳遞給至少一個備庫,如果在這個等待過程中主庫Crash,那麼也可能備庫和主庫不一致,這是很致命的。(在主庫恢復後,可以通過引數Rpl_semi_sync_master_no_tx觀察) 

     如果主備網路故障或者備庫掛了,主庫在事務提交後等待10秒(rpl_semi_sync_master_timeout的預設值)後,就會繼續。這時,主庫就會變回原來的非同步狀態。 

    MySQL在載入並開啟Semi-sync外掛後,每一個事務需等待備庫接收日誌後才返回給客戶端。如果做的是小事務,兩臺主機的延遲又較小,則Semi-sync可以實現在效能很小損失的情況下的零資料丟失。 

   主機Crash時的處理 

備庫Crash時,主庫會在某次等待超時後,關閉Semi-sync的特性,降級為普通的非同步複製,這種情況比較簡單。 

主庫Crash後,那麼可能存在一些事務已經在主庫Commit,但是還沒有傳給任何備庫,我們姑且稱這類事務為”牆頭事務”。”牆頭事務”都是沒有返回給客戶端的,所以發起事務的客戶端並不知道這個事務是否已經完成。 

這時,如果客戶端不做切換,只是等Crash的主庫恢復後,繼續在主庫進行操作,客戶端會發現前面的”牆頭事務”都已經完成,可以繼續進行後續的業務處理;另一種情況,如果客戶端Failover到備庫上,客戶端會發現前面的“牆頭事務”都沒有成功,則需要重新做這些事務,然後繼續進行後續的業務處理。 

   可以做多個備庫,任何一個備庫接收完成日誌後,主庫就可以返回給客戶端了。 

網路傳輸在併發執行緒較多時,一次可能傳輸很多日誌,事務的平均延遲會降低。 

“牆頭事務”在牆頭上的時候,是可以被讀取的,但是這些事務在上面Failover的場景下,是被認為沒有完成的。 

     預設情況下MySQL的複製是非同步的,Master上所有的更新操作寫入Binlog之後並不確保所有的更新都被複制到Slave之上。非同步操作雖然效率高,但是在Master/Slave出現問題的時候,存在很高資料不同步的風險,甚至可能丟失資料。 
MySQL5.5引入半同步複製功能的目的是為了保證在master出問題的時候,至少有一臺Slave的資料是完整的。在超時的情況下也可以臨時轉入非同步複製,保障業務的正常使用,直到一臺salve追趕上之後,繼續切換到半同步模式。 
Master: 
INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master.so’; 
SET GLOBAL rpl_semi_sync_master_enabled=1; 
SET GLOBAL rpl_semi_sync_master_timeout=1000; (1s, default 10s) 
Slave: 
INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘semisync_slave.so’; 
SET GLOBAL rpl_semi_sync_slave_enabled=1; 
複製心跳(使用者檢測複製是否中斷) 

MySQL5.5提供的新的配置master_heartbeat_period,能夠在複製停止工作和出現網路中斷的時候幫助我們迅速發現問題。 

啟用方法: 
STOP SLAVE; 
CHANGE MASTER TO master_heartbeat_period= milliseconds; 
START SLAVE; 


Slave自動恢復同步 

在MySQL5.5版本之前,MySQL Slave例項在異常終止服務之後,可能導致複製中斷,並且relay binlog可能損壞,在MySQL再次啟動之後並不能正常恢復複製。在MySQL5.5中這一問題得到了解決,MySQL可以自行丟棄順壞的而未處理的資料,重新從master上獲取源資料,進而回複復制。 
跳過指定複製事件 

在多Master或環形複製的情況下,處於複製鏈條中間的伺服器異常,可以通過 
CHANGE MASTER TO MASTER_HOST=xxx IGNORE_SERVER_IDS=y 
跳過出問題的MySQL例項。 

自動轉換欄位型別 
MySQL5.1在基於語句的複製下,支援部分的欄位轉換,但是行級的會報錯。MySQL5.5語句和行級複製都已支援。還可以通過 SLAVE_TYPE_CONVERSIONS 控制轉換的方向。 


贈送:


一、MySQL複製概述

   ⑴、MySQL資料的複製的基本介紹

   目前MySQL資料庫已經佔去資料庫市場上很大的份額,其一是由於MySQL資料的開源性和高效能,當然還有重要的一條就是免費~不過不知道還能免費多久,不容樂觀的未來,但是我們還是要能熟練掌握MySQL資料的架構和安全備份等功能,畢竟現在它還算是開源界的老大吧!

   MySQL資料庫支援同步複製、單向、非同步複製,在複製的過程中一個伺服器充當主服務,而一個或多個伺服器充當從伺服器。主伺服器將更新寫入二進位制日誌檔案,並維護檔案的一個索引以跟蹤日誌迴圈。這些日誌可以記錄傳送到從伺服器的更新。當一個從伺服器連線主伺服器時,它通知主伺服器從伺服器在日誌中讀取的最後一次成功更新的位置。從伺服器接收從那時起發生的任何更新,然後封鎖並等待主伺服器通知新的更新。

請注意當你進行復制時,所有對複製中的表的更新必須在主伺服器上進行。否則,你必須要小心,以避免使用者對主伺服器上的表進行的更新與對從伺服器上的表所進行的更新之間的衝突。

   單向複製有利於健壯性、速度和系統管理:

   健壯性:主伺服器/從伺服器設定增加了健壯性。主伺服器出現問題時,你可以切換到從伺服器作為備份。

   速度快:通過在主伺服器和從伺服器之間切分處理客戶查詢的負荷,可以得到更好的客戶響應時間。SELECT查詢可以傳送到從伺服器以降低主伺服器的查詢處理負荷。但修改資料的語句仍然應傳送到主伺服器,以便主伺服器和從伺服器保持同步。如果非更新查詢為主,該負載均衡策略很有效,但一般是更新查詢。

   系統管理:使用複製的另一個好處是可以使用一個從伺服器執行備份,而不會干擾主伺服器。在備份過程中主伺服器可以繼續處理更新。

   ⑵、MySQL資料複製的原理

   MySQL複製基於主伺服器在二進位制日誌中跟蹤所有對資料庫的更改(更新、刪除等等)。因此,要進行復制,必須在主伺服器上啟用二進位制日誌。

   每個從伺服器從主伺服器接收主伺服器已經記錄到其二進位制日誌的儲存的更新,以便從伺服器可以對其資料拷貝執行相同的更新。

   認識到二進位制日誌只是一個從啟用二進位制日誌的固定時間點開始的記錄非常重要。任何設定的從伺服器需要主伺服器上的在主伺服器上啟用二進位制日誌時的資料庫拷貝。如果啟動從伺服器時,其資料庫與主伺服器上的啟動二進位制日誌時的狀態不相同,從伺服器很可能失敗。

   將主伺服器的資料拷貝到從伺服器的一個途徑是使用LOAD DATA FROM MASTER語句。請注意LOAD DATA FROM MASTER目前只在所有表使用MyISAM儲存引擎的主伺服器上工作。並且,該語句將獲得全域性讀鎖定,因此當表正複製到從伺服器上時,不可能在主伺服器上進行更新。當我們執行表的無鎖熱備份時,則不再需要全域性讀鎖定。

   MySQL資料複製的原理圖大致如下:

從上圖我們可以看出MySQL資料庫的複製需要啟動三個執行緒來實現:

   其中1個在主伺服器上,另兩個在從伺服器上。當發出START SLAVE時,從伺服器建立一個I/O執行緒,以連線主伺服器並讓它傳送記錄在其二進位制日誌中的語句。主伺服器建立一個執行緒將二進位制日誌中的內容傳送到從伺服器。該執行緒可以識別為主伺服器上SHOW PROCESSLIST的輸出中的Binlog Dump執行緒。從伺服器I/O執行緒讀取主伺服器Binlog Dump執行緒傳送的內容並將該資料拷貝到從伺服器資料目錄中的本地檔案中,即中繼日誌。第3個執行緒是SQL執行緒,是從伺服器建立用於讀取中繼日誌並執行日誌中包含的更新。

   在前面的描述中,每個從伺服器有3個執行緒。有多個從伺服器的主伺服器建立為每個當前連線的從伺服器建立一個執行緒;每個從伺服器有自己的I/O和SQL執行緒。

   這樣讀取和執行語句被分成兩個獨立的任務。如果語句執行較慢則語句讀取任務沒有慢下來。例如,如果從伺服器有一段時間沒有執行了,當從伺服器啟動時,其I/O執行緒可以很快地從主伺服器索取所有二進位制日誌內容,即使SQL執行緒遠遠滯後。如果從伺服器在SQL執行緒執行完所有索取的語句前停止,I/O 執行緒至少已經索取了所有內容,以便語句的安全拷貝儲存到本地從伺服器的中繼日誌中,供從伺服器下次啟動時執行。這樣允許清空主伺服器上的二進位制日誌,因為不再需要等候從伺服器來索取其內容。

二、實列說明MySQL的主從複製架構和實現詳細過程

     主從架構資料庫的複製圖如下:

其配置詳細過程如下:

   1、環境架構:

       RedHat Linux Enterprise 5.8         mysql-5.5.28-linux2.6-i686.tar

       Master:172.16.7.1/16                 Slave:172.16.7.2/16

   2 、安裝mysql-5.5.28,需要在主節點和備節點上安裝mysql

       Master:

       安裝環境準備:

[sql] view
plain
 copy

 print?

  1. 為mysql的安裝提供前提環境和初始化安裝mysql  
  2. 建立資料庫目錄  
  3. # mkdir /mydata/data –pv  
  4. 建立mysq使用者  
  5. # useradd -r mysql  
  6. 修改許可權  
  7. # chown -R mysql.mysql /mydata/data/  
  8. 使用mysql-5.5通用二進位制包安裝  
  9. 解壓mysql軟體包  
  10. # tar xf mysql-5.5.28-linux2.6-i686.tar.gz-C /usr/local/  
  11. 建立連線,為了方便檢視mysql的版本等資訊  
  12. # cd /usr/local/  
  13. #ln –sv mysql-5.5.28-linux2.6-i686.tar.gzmysql  
  14. 修改屬主屬組  
  15. # cd mysql  
  16. # chown -R root.mysql ./*  
  17. 初始化資料庫  
  18. # scripts/mysql_install_db –user=mysql –datadir=/mydata/data/  
  19. 提供配置檔案  
  20. # cp support-files/my-large.cnf /etc/my.cnf  
  21. 提供服務指令碼  
  22. # cp support-files/mysql.server/etc/rc.d/init.d/mysqld  
  23. 新增至服務列表  
  24. # chkconfig –add mysqld  
  25. # chkconfig –list mysqld  
  26. # chkconfig mysqld on  
  27. 編輯配置檔案,提供資料目錄  
  28. # vim /etc/my.cnf  
  29. # The MySQL server  修改mysqld伺服器端的內容  
  30. log-bin=master-bin 主伺服器二進位制日誌檔案字首名  
  31. log-bin-index=master-bin.index  索引檔案  
  32. innodb_file_per_table= 1     開啟innodb的一表一個檔案的設定  
  33. server-id       = 1          必須是唯一的  
  34. datadir =/mydata/data        資料目錄路徑  
  35. 啟動mysql服務  
  36. # servicemysqld start  
  37. 為了便於下面的測試,設定環境變數  
  38. # vim/etc/profile.d/mysql.sh  
  39. export PATH=$PATH:/usr/local/mysql/bin  
  40. 執行環境變數指令碼,使其立即生效  
  41. # . /etc/profile.d/mysql.sh  


 啟動服務並進行相關的測試:

 mysql的安裝配置完成,下面增加一個用於同步資料的賬戶並設定相關的許可權吧!

[sql] view
plain
 copy

 print?

  1. 建立使用者賬戶  
  2. mysql> grant replication slave on *.* to `chris`@`172.16.%.%` identified by `work`;  
  3. 重新整理資料使其生效  
  4. mysql> flush privileges;  

   至此我們mysql的Master設定完成,下面進行slave端的設定吧!

   Slave:

   安裝環境配置:

[sql] view
plain
 copy

 print?

  1. 建立mysql資料庫目錄  
  2. # mkdir /mydata/data –pv  
  3. 建立mysql使用者  
  4. # useradd -r mysql  
  5. 修改資料目錄許可權  
  6. # chown -R mysql.mysql /mydata/data/  
  7. 使用mysql-5.5通用二進位制包安裝mysql  
  8. 解壓mysql軟體包  
  9. # tar xf mysql-5.5.28-linux2.6-i686.tar.gz-C /usr/local/  
  10. 建立連線,便於檢視mysql的版本等資訊  
  11. # cd /usr/local/  
  12. # ln –sv mysql-5.5.28-linux2.6-i686.tar.gzmysql  
  13. 修改mysql屬主屬組  
  14. # cd mysql  
  15. # chown -R root.mysql ./*  
  16. 初始化mysql資料庫  
  17. # scripts/mysql_install_db –user=mysql–datadir=/mydata/data/  
  18. 提供mysql配置檔案  
  19. # cp support-files/my-large.cnf /etc/my.cnf  
  20. 提供服務指令碼  
  21. # cp support-files/mysql.server /etc/init.d/mysqld  
  22. 新增至服務列表  
  23. # chkconfig –add mysqld  
  24. 編輯配置檔案  
  25. # vim /etc/my.cnf  
  26. # The MySQL server  
  27. #log-bin=mysql-bin      禁用二進位制日誌,從伺服器不需要二進位制日誌檔案  
  28. datadir = /mydata/data  mysql的資料目錄  
  29. relay-log = relay-log   設定中繼日誌  
  30. relay-log-index = relay-log.index  中繼日誌索引  
  31. innodb_file_per_table = 1  
  32. server-id       = 2    id不要和主伺服器的一樣  
  33. 設定環境變數  
  34. # vim/etc/profile.d/mysql.sh  
  35. export PATH=$PATH:/usr/local/mysql/bin  
  36. 執行此指令碼(匯出環境變數)  
  37. # . /etc/profile.d/mysql.sh  
  38. 啟動服務  
  39. # service mysqld start  


  到這slave服務的mysql安裝和配置完成,下面啟動slave複製吧,開啟之前先檢視下從服務上的二進位制檔案吧

[sql] view
plain
 copy

 print?

  1. mysql> show master status; #在Master上執行檢視二進位制檔案  
  2. 在從伺服器上開啟複製功能  
  3. change master to master_host=`172.16.7.1`,master_user=`chris`,master_password=`work`,master_log_file=`master-bin.000001`,master_log_pos=407;  
  4. 開啟複製功能  
  5. mysql>start slave;  

至此我們的mysql伺服器的主從複製架構已經基本完成,下面開啟服務並測試測試吧~

在從伺服器開啟複製程式:mysql>start slave;

   至此我們mysql伺服器的主從複製架構已經完成,但是我們現在的主從架構並不完善,因為我們的從服務上還可以進行資料庫的寫入操作,一旦使用者把資料寫入到從伺服器的資料庫內,然後從伺服器從主伺服器上同步資料庫的時候,會造成資料的錯亂,從而會造成資料的損壞,所以我們需要把從伺服器設定成只讀~方法如下:

注意:read-only = ON ,這項功能只對非管理員組以為的使用者有效!

OK,此致我們的mysql基於主從架構的複製功能已經搭建全部完成~下面介紹下關於mysql資料目錄下面各個檔案的功能和作用!

   由於二進位制檔案的緩衝區內,當我們的伺服器當機的時候,快取區內的資料並沒有同步到二進位制日誌檔案內的時候,那就悲劇了,緩衝區內的資料就無法找回了,為了防止這種情況的傳送,我們通過設定mysql直接把二進位制檔案記錄到二進位制檔案而不再緩衝區內停留。

sync-binlog = ON 在主伺服器上進行設定,用於事務安全

  從上面我們可以看到從伺服器啟動的時候其Slave_IO_Running: Yes和Slave_SQL_Running: Yes是自動啟動的,但是有時候我們在主服務上進行的誤操作等,也會直接同步到從伺服器上的,要想恢復那就難了,所以我們需要關閉其自動執行功能,讓其能夠停止,skip-slave-start = 1 ,讓其不開啟自動同步,但是遺憾的是mysql5.28上已經沒有了,我們可以通過停止相關執行緒來實現:

mysql>STOP SLAVE 或STOP SLAVE  IO_THREAF或STOP SLAVE SQL_THREAD

注意:從伺服器的所有操作日誌都會被記錄到資料目錄下的錯誤日誌中!

三、MySQL的半同步複製

   實現半同步複製的功能很簡單,只需在mysql的主伺服器和從伺服器上安裝個google提供的外掛即可實現,

   主服務上使用semisync_master.,從伺服器上使用sosemisync_slave.so外掛即可實現,外掛在mysql通用二進位制的mysql/lib/plugin目錄內。

其配置步驟如下

1、分別在主從節點上安裝相關的外掛

master:

[sql] view
plain
 copy

 print?

  1. 安裝外掛:mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME `semisync_master.so`;  
  2. 啟動模組:mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;  
  3. 設定超時時間:mysql> SET GLOBAL rpl_semi_sync_master_timeout = 1000;  

1
2
3
4
slave:
安裝外掛:msyql>
INSTALL PLUGIN rpl_semi_sync_slave SONAME 
`semisync_slave.so`;
啟動模組:mysql>
SET GLOBAL rpl_semi_sync_slave_enabled = 
1;
重啟程式使其模組生效:mysql>
STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;



  上面的設定時在mysql程式內動態設定了,會立即生效但是重啟服務以後就會失效,為了保證永久有效,需要把相關配置寫到主、從伺服器的配置檔案my.cnf內:

[sql] view
plain
 copy

 print?

  1. 在Master和Slave的my.cnf中編輯:  
  2. On Master  
  3. [mysqld]  
  4. rpl_semi_sync_master_enabled=1  
  5. rpl_semi_sync_master_timeout=1000   #此單位是毫秒  
  6. On Slave  
  7. [mysqld]  
  8. rpl_semi_sync_slave_enabled=1  

  確認半同步功能已經啟用,通過下面的操作進行檢視

[sql] view
plain
 copy

 print?

  1. master:  
  2. mysql> CREATE DATABASE asyncdb;  
  3. master> SHOW STATUS LIKE `Rpl_semi_sync_master_yes_tx`;  
  4. slave> SHOW DATABASES;  
  5. 其測試過程如下  

然後把從伺服器上的複製程式開啟,

  我們至此已經實現了mysql資料庫複製的半同步方式的架構,並且通過測試檢視了複製功能,下面我們進行雙主模型架構吧。

四、MySQL設定主-主複製:master<–>slave 

1、在兩臺伺服器上各自建立一個具有複製許可權的使用者;讓兩個資料庫互為主從的關係

2、修改配置檔案:

把上面的連個資料庫的配置檔案重新配置,其配置如下 

[sql] view
plain
 copy

 print?

  1. # 主伺服器上  
  2. [mysqld]  
  3. server-id = 1  
  4. log-bin = mysql-bin  
  5. relay-log = relay-mysql  
  6. relay-log-index = relay-mysql.index  
  7. auto-increment-increment = 2           #每次跳兩個數。  
  8. auto-increment-offset = 1              #從1開始。  


[sql] view
plain
 copy

 print?

  1. [mysqld]  
  2. server-id = 2  
  3. log-bin = mysql-bin  
  4. relay-log = relay-mysql  
  5. relay-log-index = relay-mysql.index  
  6. auto-increment-increment = 2  
  7. auto-increment-offset = 2  

  如果此時兩臺伺服器均為新建立,且無其它寫入操作,各伺服器只需記錄當前自己二進位制日誌檔案及事件位置,以之作為另外的伺服器複製起始位置即可

[sql] view
plain
 copy

 print?

  1. master:檢視日誌檔案資訊  
  2. mysql> show master status;  
  3. +——————+———-+————–+——————+  
  4. | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |  
  5. +——————+———-+————–+——————+  
  6. | mysql-bin.000001 |      107 |              |                  |  
  7. +——————+———-+————–+——————+  
  8. Slave:檢視伺服器日誌檔案資訊  
  9. mysql> show master status;  
  10. +——————+———-+————–+——————+  
  11. | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |  
  12. +——————+———-+————–+——————+  
  13. | mysql-bin.000001 |      107 |              |                  |  
  14. +——————+———-+————–+——————+  
  15. 1 row in set (0.00 sec)  

 在各個伺服器上建立賬號和許可權,來進行同步設定

1
2
3
master:
mysql>
GRANT REPLICATION SLAVE ON *.* TO 
`chrislee`@`172.16.%.%` IDENTIFIED
BY 
`work`;
mysql>
flush privileges;

[sql] view
plain
 copy

 print?

  1. slave:  
  2. mysql> GRANT REPLICATION SLAVE ON *.* TO `chrisli`@`172.16.%.%` IDENTIFIED BY `work`;  
  3. mysql> flush privileges  

在各伺服器上指定對另一臺伺服器為自己的主伺服器即可:

[sql] view
plain
 copy

 print?

  1. server1  
  2. mysql> CHANGE MASTER TO MASTER_HOST=`172.16.7.2`,MASTER_USER=`chrisli`,MASTER_PASSWORD=`work`,MASTER_LOG_FILE=`mysql-bin.000001`,MASTER_LOG_POS=344;  

[sql] view
plain
 copy

 print?

  1. server2:  
  2. mysql> CHANGE MASTER TO MASTER_HOST=`172.16.7.1`,MASTER_USER=`chrislee`,MASTER_PASSWORD=`work`,MASTER_LOG_FILE=`mysql-bin.000001`,MASTER_LOG_POS=345;  

雙主架構配置基本完成,下面在各自上面啟動複製程式吧~並進行測試:

轉載自:http://chrinux.blog.51cto.com/6466723/1204586


相關文章