MySQL 5.5 主從複製

 

MySQL 5.5 主從複製的原理、過程
 
分爲同步複製和異步複製,實際複製架構中大部分爲異步複製。複製的基本過程以下: 
1)、Slave上面的IO進程鏈接上Master,並請求從指定日誌文件的指定位置(或者從最開始的日誌)以後的日誌內容;  

2)、Master接收到來自Slave的IO進程的請求後,經過負責複製的IO進程根據請求信息讀取指定日誌指定位置以後的日誌信息,返回給Slave的IO進程。返回信息中除了日誌所包含的信息以外,還包括本次返回的信息已經到Master端的bin-log文件的名稱以及bin-log的pos位置;  

3)、Slave的IO進程接收到信息後,將接收到的日誌內容依次添加到Slave端的中繼日誌(relay-log)文件的最末端,並將讀取到的Master端的bin-log的文件名和位置記錄到master.info文件中,以便在下一次讀取的時候可以清楚的告訴Master「我須要從某個bin-log的哪一個pos位置開始日後的日誌內容,請發給我」;

4)、Slave的sql進程檢測到relay-log中新增長了內容後,會立刻解析relay-log的內容成爲在Master端真實執行時候的那些可執行的內容,並在自身執行。   

Slave端的雙進程複製提高可靠性
Mysql爲了解決這個風險並提升複製的性能,將Slave端的複製改成兩個進程來完成。提出這個改進方案的人是Yahoo!的一位工程師「Jeremy Zawodny」。這樣既解決了性能問題,又縮短了異步的延時時間,同時也減小了可能存在的數據丟失量。固然,即便是換成了如今這樣兩個線程處理之後,一樣也仍是存在Slave數據延時以及數據丟失的可能性的,畢竟這個複製是異步的。只要數據的更改不是在一個事物中,這些問題都是會存在的。若是要徹底避免這些問題,就只能用mysql的cluster來解決了。不過mysql的cluster是內存數據庫的解決方案,須要將全部數據都load到內存中,這樣就對內存的要求就很是大了,對於通常的應用來講可實施性不是太大。

經常使用主從複製架構 
Mysql複製環境90%以上都是一個Master帶一個或者多個Slave的架構模式,主要用於讀壓力比較大的應用的數據庫端廉價擴展解決方案。由於只要master和slave的壓力不是太大(尤爲是slave端壓力)的話,異步複製的延時通常都不多不多。尤爲是自slave端的複製方式改爲兩個進程處理以後,更是減少了slave端的延時。而帶來的效益是,對於數據實時性要求不是特別的敏感度的應用,只須要經過廉價的pc server來擴展slave的數量,將讀壓力分散到多臺slave的機器上面,便可解決數據庫端的讀壓力瓶頸。這在很大程度上解決了目前不少中小型網站的數據庫壓力瓶頸問題,甚至有些大型網站也在使用相似方案解決數據庫瓶頸。


1、準備實驗環境:
    主(Master)機IP: 192.168.137.26
    從(Slave) 機IP: 192.168.137.27
    兩MySQL服務器均是源碼包編譯安裝

2、向主(Master)機添加遠程登陸的受權用戶
    1.向主(Master)服務器添加用戶:
      @ 用戶名: slave4
      @ 密  碼: 789
      @ 容許自: 192.168.137.27 機器登陸

      受權方式1: 此種受權是可遠程登陸Master,僅用於主從複製沒有其它任何select insert update等權限【推薦】
      mysql> grant replication slave on *.* to 'slave4'@'192.168.137.27' identified by '789';

      受權方式2: 此種受權是對用戶不但可遠程登陸Master,還可擁有對Master包括主從複製的其它全部select insert update等權限
      mysql> grant all on *.* to 'slave6'@'192.168.137.28' identified by '789';

    2.刷新受權表:
      mysql> flush privileges;

    3.查看受權結果:
      mysql> show grants for 'slave4'@'192.168.137.27';

    4.測試從Slave端登陸遠程主(Master)機:
      # /usr/local/mysql/bin/mysql -uslave4 -p789 -h192.168.137.26

    5.從主(Master)機查看全部鏈接登陸本機的客戶端狀況:
      mysql> show processlist \G


3、主(Master)機配置
    vi編輯打開mysql配置文件
    # vi /usr/local/mysql/etc/my.cnf

    找到從約第56行開始確認如下三項:
    [mysqld]
    log-bin=mysql-bin    # 確認開啓binlog日誌
    binlog_format=mixed  # 確認binlog日誌格式爲mixd混合類型
    server-id = 1        # 在整個主從架構內指定一個惟一的server-id,範圍:1^32


4、從(Slave)機配置-【基本】
    vi編輯打開mysql配置文件
    # vi /usr/local/mysql/etc/my.cnf

    找到從約第56行開始確認如下三項: 
    [mysqld]
    log-bin=mysql-bin    # 確認也開啓binlog日誌
    binlog_format=mixed  # 確認binlog日誌格式爲mixd混合類型
    server-id = 2        # 在整個主從架構內指定一個惟一的server-id,範圍:1^32 ◆


    從(Slave)機配置-【可選】
    下面是生產階段可能要用的功能,這些功能只能在從機的配置文件的[mysqld]區塊裏手工配置,沒法經過 change master to ...命令實現。
    1.白名單 - 只想複製某(些)個庫:
      replicate_do_db=zyyshop                 # 追加複製zyyshop庫
      replicate_do_db=test                    # 追加只複製test庫
      總結: 至關於只複製 zyyshop、test 兩個庫
            若是採用徹底在配置文件裏配置主(Master)機信息的方法,此項須添加,不然可能致使mysqld啓動不了 

    2.白名單 - 只想複製某(些)個庫(的全部表)
      replicate_wild_do_table=zyyshop.%       # 追加複製zyyshop庫的全部表
      replicate_wild_do_table=test.%          # 追加複製test庫的全部表
      總結:也是至關於只複製 zyyshop、test 兩個庫。

    3.白名單 - 只想複製某(些)個庫(的部分表)
      replicate_wild_do_table=zyyshop.stu     # 追加zyyshop.stu表
      replicate_wild_do_table=test.project    # 追加test.project表
      總結:至關於只複製zyyshop.stu、test.project兩個表。

    4.黑名單 - 想忽略對mysql和test數據庫的複製
      replicate_ignore_db=mysql               # 追加mysql庫爲忽略
      replicate_ignore_db=test                # 追加test庫爲忽略
      總結:至關於將mysql和test兩數據庫追加到忽略列表,將不會被複制。
    
    5.黑名單 - 想忽略對某些庫的某些表的複製
      replicate_wild_ignore_table=mysql.users # 追加mysql.users表爲忽略
      總結:本步驟是至關於追加了mysql.users具體的表被忽略,其它表照常會被複制。
      
    6.若是想實現「主-->從-->從」的鏈式架構,由於在默認狀況下,from主(Master)機copy過來的數據不會寫入從(Slave)機的binlog日誌裏,
      而是寫入中繼日誌(localhost-relay-bin.00000x)裏,因此本機若是還須要充當其它機器的主機,就將從主機複製來的數據寫入從庫時同
      時也顯式地寫入本地binlog日誌,添加以下配置:
      log-slave-updates =1

5、在主(Master)機端操做:執行命令刷新主機binlog日誌記錄,查看主機的最後日誌文件及最後pos起始點
    mysql> flush logs;
    mysql> show master status;
    +------------------+----------+--------------+------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000009 |      107 |              |                  |
    +------------------+----------+--------------+------------------+

6、在從(Slave)機啓動slave服務
    1.使用root用戶登陸到從(Slave)機
      # /usr/local/mysql/bin/mysql -uroot -p123456

    2.在從(Slave)上執行命令,動態改變鏈接到主(Master)機的配置,生成或更新master.info文件:
      注: 在生產環境中,若是心跳感應到主機意外宕機,應用程序應該按預案選定出一臺新主機,而其它的從機都須要執行一次下面
          的 change master to ...語句,切換本身從屬到新主機,這樣比較靈活,操做的實質是更新master.info文件,查看此文件也
          能發現MySQL實際上是隻能支持「一主多從」架構,而不能像Redis那樣還能夠支持多主一從架構。

      mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='mysql-bin.000009', MASTER_LOG_POS=107;

      善於使用?查看詳細選項
      mysql> ? change master to

      經常使用選項:
       master_host='192.168.137.26' 遠程主(Master)機IP      
       master_user='slave4',        登陸遠程主(Master)機 用戶名
       master_password='789',       登陸遠程主(Master)機 密碼

      不經常使用選項:      
       MASTER_LOG_FILE='mysql-bin.000009' 指定從哪一個binlog文件複製(若是不加此參數默認是最先的binlog日誌)
       MASTER_LOG_POS=107                 指定從哪一個binlog文件的哪一個pos點開始複製(若是不加此參數默認是最先的pos點)
       MASTER_PORT=3306,                  遠程主(Master)機端口
       MASTER_HEARTBEAT_PERIOD=60         多長時間探測一次主服務器是否在線 單位:秒
       MASTER_CONNECT_RETRY=10;           沒法鏈接主服務器的時候重試鏈接的間隔時間 單位:秒


    3.啓動IO線程和SQL線程,生成master.info文件,查看從(Slave)機狀態:
      mysql> start slave;
      mysql> show slave status \G;

      若是看到以下狀態說明同步成功:             
           Slave_IO_Running: Yes
          Slave_SQL_Running: Yes
      Seconds_Behind_Master: 0


    4.報錯處理!若是「Slave_SQL_Running: No」,程序可能在slave上進行了寫操做,也多是slave機器重起後,事務回滾形成的。
      解決方法一: 
      mysql> stop slave;
      mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
      mysql> start slave;
      mysql> show slave status \G;

      解決方法二:
      主(Master)上:
      mysql> show master status;  //主機上查看最新的binlog日誌名及pos點

      從(Slave)機上:
      mysql> stop slave;          //從機停掉slave服務
      mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='主機最新binlog日誌名', MASTER_LOG_POS=最新pos點;
      mysql> start slave;
      mysql> show slave status \G;
      


7、【實驗】若是開始的環境不是主從架構,跑了一段時間主(Master)機已經有了數據,且主機的binlog日誌已經不完整了,可由兩種方案:

    方案一(推薦):對主(Master)機作一次完整的mysqldump備份,拷貝到從(Slave)機執行從機恢復,而後從機再開啓slave服務

      A.【主機操做】備份主機數據(好比:test和zyyshop是須要之後同步的庫)
         # /usr/local/mysql/bin/mysqldump -uroot -p123456 -lF --log-error=/root/myDump.err -B test zyyshop > /root/test_zyyshop.sql

      B.【主機操做】當即查看一下主機的最新的binlog日誌,並記錄binlog日誌名和pos點,從機就從這兒開始同步便可:
         # /usr/local/mysql/bin/mysql -uroot -p123456
         mysql> show master status;
         +------------------+----------+--------------+------------------+
         | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
         +------------------+----------+--------------+------------------+
         | mysql-bin.000012 |      107 |              |                  |
         +------------------+----------+--------------+------------------+

      C.【主機操做】將備份的文件直接恢復到遠程的從(Slave)機數據庫上:     
         方法1:先將 test_zyyshop.sql 備份文件 SCP 拷貝到遠程從(Slave)機,再登陸到遠程從機恢復:
                A.拷貝備份數據到從機:
                  # scp /root/test_zyyshop.sql root@192.168.137.27:/root/masterdb.sql
                  須要兩臺機器都安裝scp纔可,scp屬於openssh-clients這個包,安裝方法:# yum install -y openssh-clients

                B.[從機操做]將從機的備份數據恢復:
                  # /usr/local/mysql/bin/mysql -uroot -p123456 -v < /root/masterdb.sql

         方法2:直接恢復到遠程從(Slave)機上:
                # /usr/local/mysql/bin/mysql -uroot -p123456 -h192.168.137.27 -v < /root/test_zyyshop.sql

         至此從機已將主機的備份文件恢復到從機,接下來只要不斷向主機同步binlog日誌就OK了。

      D.[從機操做] 在從(Slave)上執行命令,動態改變鏈接到主(Master)機的配置,生成或更新master.info文件:
        # /usr/local/mysql/bin/mysql -uroot -p123456        

        mysql> change master to master_host='192.168.137.26', master_user='slave4', master_password='789', MASTER_LOG_FILE='mysql-bin.000012', MASTER_LOG_POS=107;  

        mysql> start slave;
        mysql> show slave status \G;

        *************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.137.26
                  Master_User: slave4
                  Master_Port: 3306
                Connect_Retry: 10
              Master_Log_File: mysql-bin.000012
          Read_Master_Log_Pos: 107
               Relay_Log_File: zzx-relay-bin.000002
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000012
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

        ................

    小結:若是slave啓動一切正常,就成功了!



    方案二:打包主機的數據目錄拷貝到從(Slave)機進行從機恢復,而後從機再開啓slave服務
            ★ 注: 此法適用於MyISAM引擎表,不適用於Innodb引擎表。

      # /usr/local/mysql/bin/mysql -uroot -p123456

      A.【主機操做】對主(Master)機全部表進行「讀鎖」:     
         mysql> flush tables with read lock;

         查看一下主機的最新的binlog日誌,並記錄binlog日誌名和pos點,從機就從這兒開始同步便可:
         mysql> show master status;
         +------------------+----------+--------------+------------------+
         | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
         +------------------+----------+--------------+------------------+
         | mysql-bin.000012 |      107 |              |                  |
         +------------------+----------+--------------+------------------+

      B.【主機操做】進入數據目錄,打包須要的數據庫包
        # cd /usr/local/mysql/data/
        # tar -zcvf  test.tar.gz test
        # tar -zcvf zyyshop.tar.gz zyyshop

      C.【主機操做】打包完成對主(Master)機全部表「解鎖」:
        mysql> unlock tables;

      D.【主機操做】將兩數據庫打包文件SCP到從(Slave)機的數據目錄中:
        # scp test.tar.gz zyyshop.tar.gz root@192.168.137.27:/usr/local/mysql/data/

      E.[從機操做]進入數據存放目錄,解壓數據包(生成數據庫):
        # cd /usr/local/mysql/data/ 
        # tar -zxvf test.tar.gz
        # tar -zxvf zyyshop.tar.gz

      F.[從機操做] 在從(Slave)上執行命令(改變)鏈接主(Master)機,生成或更新master.info文件:
        此步同上D步,略......
      
   
      
8、主從複製中的幾個重要文件
    IO線程只負責從主(Master)機端複製 mysql-bin.00000x 日誌,並把複製來的數據所有都放到 localhost-relay-bin.00000n 日誌裏。
    SQL線程讀取中繼日誌(relay-log.info)裏的信息,將 localhost-relay-bin.00000n 日誌裏的數據寫入本地從(Slave)機。

    1.master.info 做用:
      A.記錄鏈接到主(Master)機的帳號和密碼;
      B.記錄複製到主(Master)機的哪一個二進制文件和複製到二進制文件的位置(pos點);

    2.relay-log.info 中繼日誌,做用:
      A.記錄了寫了多少數據到本地從(Slave)機中;

      
附、show slave status\G 返回信息解析:
    *************************** 1. row ***************************  
                   Slave_IO_State: Waiting for master to send event   # IO的線程的狀態  
                      Master_Host: 192.168.137.26                     # 連接主服務器的IP  
                      Master_User: mark                               # 登陸主服務器用戶名  
                      Master_Port: 3306                               # 登陸主服務器端口  
                    Connect_Retry: 10                                 # 主從斷開後,多少秒從新連接  
                  Master_Log_File: mysql-bin.000004                   # 從服務器I/O 線程當前讀取的主服務器二進制日誌文件的名字  
              Read_Master_Log_Pos: 190                                # 從服務器I/O 線程從當前的主服務器二進制日誌中讀取的位置起點。  
                   Relay_Log_File: ip_lb-relay-bin.000002             # 從服務器SQL 線程當前讀取並執行的中繼日誌文件的名字  
                    Relay_Log_Pos: 336                                # 從服務器SQL 線程當前從中繼日誌中讀取執行的位置起點。  
            Relay_Master_Log_File: mysql-bin.000004                   # 從服務器中的SQL進程中正在執行的語句的位置  
                 Slave_IO_Running: Yes     # 從服務器的IO線程運行是否開啓  
                Slave_SQL_Running: Yes     # 從服務器的SQL線程運行是否開啓  
                  Replicate_Do_DB:         # 主從須要複製的數據庫名  
              Replicate_Ignore_DB:         # 主從不須要複製的數據庫名  
               Replicate_Do_Table:         # 主從須要複製的表           
           Replicate_Ignore_Table:         # 主從不須要複製的表  
          Replicate_Wild_Do_Table:         # 能夠跨庫複製的表  
      Replicate_Wild_Ignore_Table:         # 不能跨庫複製的表  
                       Last_Errno: 0       # 最後複製的錯誤號...0表示沒有錯誤  
                       Last_Error:         # 最後複製的錯誤信息  
                     Skip_Counter: 0       # 最近被使用的用於SQL_SLAVE_SKIP_COUNTER的值。(這個值表示跳過多少個事件在來執行SQL)  
              Exec_Master_Log_Pos: 190     # SQL線程執行到主服務器log-bin文件的位置.若是這個值與Read_Master_Log_Pos同樣.則能夠證實    
                  Relay_Log_Space: 492     # 全部原有的中繼日誌結合起來的總大小。  
                  Until_Condition: None    # 在START SLAVE語句的UNTIL子句中指定的值  
                   Until_Log_File:         # 在START SLAVE語句的UNTIL子句中指定的值  
                    Until_Log_Pos: 0       # 在START SLAVE語句的UNTIL子句中指定的值  
               Master_SSL_Allowed: No      # 這些字段顯示了被從屬服務器使用的參數。這些參數用於鏈接主服務器。  
               Master_SSL_CA_File:   
               Master_SSL_CA_Path:   
                  Master_SSL_Cert:   
                Master_SSL_Cipher:   
                   Master_SSL_Key:   
            Seconds_Behind_Master: 0   # 本字段是從屬服務器「落後」多少的一個指示。當從屬SQL線程正在運行時(處理更新),  
                                         本字段爲在主服務器上由此線程執行的最近的一個事件的時間標記開始,已通過的秒數。  
                                         當此線程被從屬服務器I/O線程遇上,並進入閒置狀態,等待來自I/O線程的更多的事件時,本字段爲零。  
                                         總之,本字段測量從屬服務器SQL線程和從屬服務器I/O線程之間的時間差距,單位以秒計。  
                                         若是主服務器和從屬服務器之間的網絡鏈接較快,則從屬服務器I/O線程會很是接近主服務器,  
                                         因此本字段可以十分近似地指示,從屬服務器SQL線程比主服務器落後多少。  
                                         若是網絡較慢,則這種指示不許確;從屬SQL線程常常會遇上讀取速度較慢地從屬服務器I/O線程,  
                                         所以,Seconds_Behind_Master常常顯示值爲0。即便I/O線程落後於主服務器時,也是如此。  
                                         換句話說,本列只對速度快的網絡有用。  
                                         即便主機和從機不具備相同的時鐘,時間差計算也會起做用(當從屬服務器I/O線程啓動時,計算
                                         時間差。並假定今後時之後,時間差保持不變)。  
                                         若是從屬SQL線程不運行,或者若是從屬服務器I/O線程不運行或未與主服務器鏈接,  
                                         則Seconds_Behind_Master爲NULL(意義爲「未知」)。  
                                         舉例說明,若是在從新鏈接以前,從屬服務器I/O線程休眠了master-connect-retry秒,則顯示NULL,  
                                         由於從屬服務器不知道主服務器正在作什麼,也不能有把握地說落後多少。  
    Master_SSL_Verify_Server_Cert: No  
                    Last_IO_Errno: 0  
                    Last_IO_Error:   
                   Last_SQL_Errno: 0  
                   Last_SQL_Error:   
      Replicate_Ignore_Server_Ids:   
                 Master_Server_Id: 1  
    1 row in set (0.00 sec)  



參考文檔:

MySQL5.5 主從複製 
http://blog.csdn.net/m582445672/article/details/7731565

mysql5.5 主從複製 (觸發器,函數,存儲引擎,事件處理)說明 
http://blog.csdn.net/m582445672/article/details/7670802

Mysql主從複製[生產環境]
http://wenku.baidu.com/link?url=a-SLn41EKYseSxikYViSqvf9IBwGh7d0NsaKPnBbZjc3sED4VF_NfpjMT5IrUhC3yeuq75geJuglzrz2RXmY41t3mVHcx9-oaNIAG6dRuIu

Slave_SQL_Running: No mysql同步故障解決方法
http://kerry.blog.51cto.com/172631/277414/
相關文章
相關標籤/搜索