MySQL主從複製異步原理以及搭建

MySQL主從複製的原理:mysql

  一、首先,MySQL主庫在事務提交時會把數據變動做爲時間events記錄在二進制日誌文件binlog中;MySQL主庫上的sync_binlog參數控制Binlog日誌以什麼樣的方式刷新到磁盤上。sql

  二、主庫推送二進制日誌文件Binlog中的事件到從庫的中繼日誌Relay Log中,以後從庫根據中繼日誌Relay Log重作數據變動操做,經過邏輯複製以此來達到主庫和從庫的數據一致。數據庫

MySQL主從複製的關鍵點:服務器

  MySQL經過3個線程來完成主從庫間的數據複製,其中Binlog Dump線程跑在主庫上,I/O線程和SQL線程跑在從庫上。當在從庫上啓動複製時,首先建立I/O線程來鏈接主庫,隨後主庫建立Binlog Dump線程讀取數據庫事件併發送給I/O線程,I/O線程獲取到事件數據後更新到從庫的中繼日誌Relay log中去,以後從庫上的SQL線程讀取中繼日誌Relay Log中更新的數據庫事件並應用到從庫上來。網絡

示意圖:併發

主庫端查看線程:異步

mysql> show processlist\G
*************************** 1. row ***************************
     Id: 55
   User: chaofeng
   Host: ip-172-31-26-133.ec2.internal:35750
     db: NULL
Command: Binlog Dump
   Time: 1433
  State: Master has sent all binlog to slave; waiting for more updates
   Info: NULL
*************************** 2. row ***************************
     Id: 56
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: starting
   Info: show processlist
2 rows in set (0.00 sec)

從主庫端的Binlog Dump線程的狀態咱們能夠看到,MySQL的複製時主庫主動推送日誌到從庫上去的,屬於「推」日誌的方式來作同步。ui

 MySQL主從複製中的各種文件spa

從MySQL的複製流程能夠看到複製過程當中涉及了兩類很是重要的日誌文件:二進制日誌文件(Binlog)和中繼日誌文件(Relay Log)線程

 二進制日誌文件會把MySQL中的全部數據修改操做以二進制的形式記錄到日誌文件中,其中包括:create、drop、insert、update、delete等。可是二進制日誌文件並不會記錄select操做,由於select並不對數據作修改。

咱們能夠來查看一下Binlog的格式,Binlog支持三種格式:Row、Statement、Mixed

mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

中繼日誌Relay log與二進制日誌文件Binlog在文件格式、內容上等都是同樣的。惟一的區別就是:從庫上的SQL線程在執行完Relay log中的事件以後,SQL線程還會自動刪除當前中繼日誌文件。這樣作的緣由是爲了不中繼日誌Relay Log過多從而佔用磁盤空間。

爲了保證從庫crash重啓以後,從庫的I/O線程和SQL線程仍然可以知道從哪裏開始繼續複製,從庫默認還會建立兩個日誌文件master.info和relay-log.info用來保存複製的進度。master.info用來保存從庫的I/O線程當前讀取的二進制日誌Binlog的進度,relay-log.info用來保存SQL線程應用中繼日誌Relay log的進度

下面青綠色表示master.info文件的信息。紫色表示relay-log.info文件的信息。

MySQL [(none)]> show slave status\G
***************************
1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.31.22.29                          #主庫IP Master_User: chaofeng                            #主庫上用戶主從複製的帳號 Master_Port: 3306                              #主庫的mysql的端口 Connect_Retry: 60 Master_Log_File: mysql-bin.000001                       #從庫I/O線程當前讀取的主庫Binlog文件名 Read_Master_Log_Pos: 915                               #從庫I/O線程讀取主庫上Binlog的位置 Relay_Log_File: ip-172-31-26-133-relay-bin.000002             #SQL線程正在應用的Relay Log Relay_Log_Pos: 479                               #SQL線程鄭州應用的Relay Log的位置
Relay_Master_Log_File: mysql-bin.000001                       #SQL線程正在應用的Relay Log對於的Binlog Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Skip_Counter: 0 Exec_Master_Log_Pos: 915                              #SQL線程正在應用Relay Log的位置對應主庫Binlog的位置                              Relay_Log_Space: 697 Master_Server_Id: 1 Master_UUID: ce15f67e-0ccc-11e9-9e0a-0af74ce261dc Master_Info_File: /data/data_mysql/master.info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: 1 row in set (0.00 sec)

搭建步驟:

主從同步的MySQL版本最好一致,咱們這裏使用兩臺機器來作演示,每臺機器均部署一個MySQL實例

master:172.31.22.29  

slave:172.31.26.133

 

一、在主庫上,設置一個複製使用的帳戶,並授予" REPLICATION SLAVE "權限。

mysql> GRANT REPLICATION SLAVE ON *.* TO 'chaofeng'@'172.31.26.133' IDENTIFIED BY '123456789';
Query OK, 0 rows affected, 0 warning (0.00 sec)

這個操做表示建立一個複製用戶chaofeng,能夠從172.31.26.133這個主機上進行鏈接,密碼爲123456789

二、在主庫這臺機器上,修改my.cnf文件,開啓binlog日誌功能,並設置server_id的值。修改完並重啓服務

[mysqld]

#secure_file_priv = /root
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
basedir = /usr/local/mysql
datadir = /data/data_mysql
log-bin=/usr/local/mysql/logs/mysql-bin.log                    #這裏我把日誌單獨放置一個目錄下。 server_id=1
log-error=/usr/local/mysql/logs/mysql.log
port = 3306

三、在主庫上,設置讀鎖定有效,這個操做是爲了確保沒有數據庫操做,以便獲取一致性的快照。

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

四、查看主庫上此時的二進制日誌名以及偏移位。

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      756 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

五、接下來咱們就開始備份主庫的數據了,這裏咱們直接經過將mysql數據目錄進行打包操做發送給從庫。由於咱們這裏的主庫服務能夠中止,所以咱們直接複製文件是最快的操做,可是在生產環境中你須要考慮不少。

[root@:vg_adn_tidbCkhsTest:172.31.22.29 /data/data_mysql]#tar -zcf mysql.tar.gz ./*
[root@:vg_adn_tidbCkhsTest:23.22.172.65:172.31.22.29 /data/data_mysql]#ls
auto.cnf  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ib_logfile2  ibtmp1  mysql  mysql.pid  mysql.tar.gz  performance_schema  sys

六、主庫完成以後咱們就能夠恢復主庫的寫操做了

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

七、將mysql.tar.gz發送給從庫。並解壓到從庫的數據目錄下

[root@:vg_adn_tidbCkhsTest:172.31.26.133 /data]#tar -zxf mysql.tar.gz -C /data/data_mysql
[root@:vg_adn_tidbCkhsTest:172.31.26.133 /data]#ls data_mysql
auto.cnf  ib_buffer_pool  ibdata1  ib_logfile0  ib_logfile1  ib_logfile2  ibtmp1  mysql  mysql.pid  performance_schema  sys

九、接下來咱們開始配置從庫,修改從庫的配置文件/etc/my.cnf,其中有個server_id參數,注意這個server_id的值必須與主庫的server_id不同,若是是多個從庫,每一個服務器的server_id值都不能相同。

[mysqld]
server_id=2

從庫沒必要開啓binlog功能。

十、在mysql5.7以上的版本中,除了保證server_id不同外,還有保證server_uuid不同才行。server_uuid的值在MySQL數據目錄下的auto.cnf文件下

查看主庫的server_uuid

[root@:vg_adn_tidbCkhsTest:172.31.22.29 /data/data_mysql]#cat auto.cnf
[auto]
server-uuid=ce15f67e-0ccc-11e9-9e0a-0af74ce261dc

查看從庫的server_uuid

[root@:vg_adn_tidbCkhsTest:172.31.26.133 /data/data_mysql]#cat auto.cnf
[auto]
server-uuid=ce15f67e-0ccc-11e9-9e0a-0af74ce261dc

 由於咱們是直接將主庫的數據目錄複製過來的,所以兩個文件下的auto.cnf的值是如出一轍的,咱們修改一下從庫的這個值,只修改一位便可,只要能保證這兩個值不同就行。

修改從庫的server_uuid值爲

server-uuid=ce15f67e-0ccc-11e9-9e0a-0af74ce261dd

十一、接下來重啓從服務器,對從數據庫服務器進行設置,這裏主要設置一下幾項:

MySQL [(none)]> CHANGE MASTER TO
          -> MASTER_HOST='172.31.22.29',
          -> MASTER_PORT=3306,
        -> MASTER_USER='chaofeng',     
-> MASTER_PASSWORD='123456789',     -> MASTER_LOG_FILE='mysql-bin.000001',     -> MASTER_LOG_POS=756; Query OK, 0 rows affected, 2 warnings (0.02 sec)

十二、從庫上啓動線程

MySQL [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)

1三、這時在slave上執行show processlist命令將顯示相似以下的信息:

MySQL [(none)]> show processlist\G
*************************** 1. row ***************************
     Id: 4
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: starting
   Info: show processlist
*************************** 2. row ***************************
     Id: 6
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 5 State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 7
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 5 State: Slave has read all relay log; waiting for more updates
   Info: NULL
3 rows in set (0.00 sec)

或者你也能夠這樣子查看:

MySQL [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.31.22.29
                  Master_User: chaofeng
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 756
               Relay_Log_File: ip-172-31-26-133-relay-bin.000002
                Relay_Log_Pos: 320
        Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 756
              Relay_Log_Space: 538
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           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
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
                  Master_UUID: ce15f67e-0ccc-11e9-9e0a-0af74ce261dc
             Master_Info_File: /data/data_mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

以上都是查看主從複製是否正常的方法,只要能看到上面標記青綠色的信息,就說明主從複製搭建成功了

 主從複製異步存在的問題:

在MySQL5.5以前的版本中,MySQL的複製是異步複製,主庫和從庫的數據之間存在必定的延遲,好比網絡故障等各類緣由,這樣子容易存在隱患就是:當在主庫寫入一個事務成功後並提交了,可是因爲從庫延遲沒有及時獲得主庫推送的Binlog日誌時,主庫忽然宕機了,那麼此時從庫就可能損失這個事務,從而形成主從不一致的情況。

所以咱們MySQL5.5版本以後引入了半同步複製的概念,看下節文章

相關文章
相關標籤/搜索