搭建MySQL主從複製及原理詳解

搭建MySQL主從複製及原理詳解

​ MySQL的複製有3中常見架構,分別是一主多從複製架構、多級複製架構和雙主複製架構。本片文章主要講解的是一主多從架構及其搭建過程,其它兩種有興趣的讀者能夠留言。mysql

1.複製簡述

​ MySQL從3.23版本開始提供複製的功能。複製是指將主數據庫的DDL和DML操做經過二進制日誌傳到複製服務器(也叫從庫)上,而後在從庫上對這些日誌從新執行(也叫重作),從而使得從庫和主庫的數據保持同步。
​ MySQL支持一臺主庫同時向多臺從庫進行復制,從庫同時也能夠做爲其餘服務器的主庫,實現鏈狀的複製。
​ MySQL複製的優勢主要包括如下3個方面:sql

  1. 若是主庫出現問題,能夠快速切換到從庫提供服務;
  2. 能夠在從庫上執行查詢操做,下降主庫的訪問壓力;
  3. 能夠在從庫上執行備份,以免備份期間影響主庫的服務。

2.複製原理

​ (1)首先,MySQL主庫在事務提交時會把數據變動做爲事件Events記錄在二進制日誌文件Binlog中;MySQL主庫上的sync_binlog參數控制Binlog日誌刷新到磁盤。
​ (2)主庫推送二進制日誌文件Binlog中的事件到從庫的中繼日誌Relay Log,以後從庫根據中繼日誌Relay Log重作數據變動操做,經過邏輯複製以此來達到主庫和從庫的數據一致。
​ MySQL經過 3個線程來完成主從庫間的數據複製:其中Binlog Dump線程跑在主庫上, I/O線程和SQL線程跑在從庫上。當在從庫上啓動複製(START SLAVE)時,首先建立 I/O線程鏈接主庫,主庫隨後建立Binlog Dump線程讀取數據庫事件併發送給 I/O線程,I/O線程獲取到事件數據後更新到從庫的中繼日誌Relay Log中去,以後從庫上的SQL線程讀取中繼日誌Relay Log中更新的數據庫事件並應用,以下圖所示:shell

<img src="C:\Users\50312\AppData\Roaming\Typora\typora-user-images\image-20201207083143526.png" alt="image-202數據庫

01207083143526" style="zoom:80%;" />服務器

3.複製涉及的各種文件

二進制日誌(Binlog)

​ 二進制日誌文件(Binlog)會把 MySQL 中的全部數據修改操做以二進制的形式記錄到日誌文件中,包括Create、Drop、Insert、Update、Delete操做等,但二進制日誌文件(Binlog)不會記錄Select操做,由於Select操做並不修改數據。
​ 二進制日誌文件Binlog格式有如下3種:架構

  • Statement:基於SQL語句級別的Binlog,每條修改數據的SQL都會保存到Binlog裏
  • Row:基於行級別,記錄每一行數據的變化,也就是將每行數據的變化都記錄到Binlog裏面,記錄得很是詳細,可是並不記錄原始SQL;在複製的時候,並不會由於存儲過程或觸發器形成主從庫數據不一致的問題,可是記錄的日誌量較Statement格式要大得多。
  • Mixed:混合Statement和Row模式,默認狀況下采用Statement模式記錄,某些狀況下會切換到Row模式,例如SQL中包含與時間、用戶相關的函數等。

中繼日誌(Relay Log)

​ 中繼日誌文件Relay Log的文件格式、內容和二進制日誌文件Binlog同樣,惟一的區別在於從庫上的SQL線程在執行完當前中繼日誌文件Relay Log中的事件以後,SQL線程會自動刪除當前中繼日誌文件Relay Log,避免從庫上的中繼日誌文件Relay Log佔用過多的磁盤空間。併發

4.搭建步驟

關閉主從機器的防火牆

# systemctl stop iptables(須要安裝iptables服務)
# systemctl stop firewalld(默認)
# systemctl disable firewalld.service(設置開啓不啓動)

主服務器配置

第一步:修改my.cnf文件

​ 修改主數據庫服務器的配置文件my.cnf,開啓BINLOG,並設置server-id的值。這兩個參數的修改須要從新啓動數據庫服務才能夠生效。函數

[mysqld]
#啓用二進制日誌
log-bin=mysql-bin
#服務器惟一ID,通常取IP最後一段
server-id=136

第二步:重啓MySQL

# systemctl restart mysqld

第三步:授予Slave從機權限

mysql> GRANT REPLICATION SLAVE ON *.* TO 'root'@'192.168.211.138'IDENTIFIED BY '123456';

第四步:刷新權限

FLUSH PRIVILEGES;

第五步:查看master的狀態

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000006 |      120 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

上圖表示,主機將從 mysql-bin.000006這個二進制文件的120行這個位置開始同步。測試

從服務器配置

第一步:修改my.cnf文件

[mysqld]
server-id=138

確保集羣中的各個服務器的server-id惟一。線程

第二步:重啓並登陸到從庫

先使用以下命令查看從機是否在運行,是的話先中止運行

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

第三步:配置從數據庫服務器

​ 指定複製用戶,主數據庫服務器IP、端口以及開始執行復制的日誌文件和位置等,具體以下:

mysql> change master to
-> master_host='master_host_name',
-> master_port='master_host_port',
-> master_user='replication_user_name',
-> master_password='replication_password',
-> master_log_file='recorded_log_file_name',
-> master_log_pos=recorded_log_position;

舉例說明以下:

mysql> change master to
    -> master_host='192.168.211.136',
    -> master_port=3306,
    -> master_user='root',
    -> master_password='123456',
    -> master_log_file='mysql-bin.000006',
    -> master_log_pos=120;

第四步:啓動slave線程

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

第五步:檢查從服務器複製功能狀態

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.211.136
                  Master_User: root
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000006
          Read_Master_Log_Pos: 120
               Relay_Log_File: mysqld-relay-bin.000002
                Relay_Log_Pos: 283
        Relay_Master_Log_File: mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
。。。。。。。省略

Slave_IO_Running: Yes 說明從庫IO線程已就緒。
Slave_SQL_Running: Yes 說明從庫SQL線程已就緒。

測試

​ 搭建成功以後,往主機中插入數據,看看從機中是否有數據

注: 若是出現複製不成功,可使用
mysql> set global sql_slave_skip_counter =1; # 忽略一個錯誤
mysql> start slave

5.存在問題:主從延時

查看主機處理狀態

​ 能夠經過SHOW PROCESSLIST命令在主庫上查看Binlog Dump線程,從BinlogDump線程的狀態能夠看到,MySQL 的複製是主庫主動推送日誌到從庫去的,是屬於「推」日誌的方式來作同步

mysql> mysql> show processlist \g;
+----+------+-----------------------+------+-------------+-------+-----------------------------------------------------------------------+------------------+
| Id | User | Host                  | db   | Command     | Time  | State                                                                 | Info             |
+----+------+-----------------------+------+-------------+-------+-----------------------------------------------------------------------+------------------+
|  3 | root | 192.168.211.1:50147   | NULL | Sleep       | 11225 |                                                                       | NULL             |
|  6 | root | 192.168.211.138:52846 | NULL | Binlog Dump |  6174 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL             |
|  7 | root | localhost             | NULL | Query       |     0 | init                                                                  | show processlist |
+----+------+-----------------------+------+-------------+-------+-----------------------------------------------------------------------+------------------+
3 rows in set (0.00 sec)

查看從機處理狀態

​ 在從庫上經過SHOW PROCESSLIST能夠看到 I/O線程和SQL線程,I/O線程等待主庫上的Binlog Dump線程發送事件並更新到中繼日誌Relay Log,SQL線程讀取中繼日誌Relay Log並應用變動到數據庫:

mysql> show processlist \g;
+----+-------------+---------------------+------+---------+------+-----------------------------------------------------------------------------+------------------+
| Id | User        | Host                | db   | Command | Time | State                                                                       | Info             |
+----+-------------+---------------------+------+---------+------+-----------------------------------------------------------------------------+------------------+
|  4 | root        | 192.168.211.1:50207 | NULL | Sleep   |  572 |                                                                             | NULL             |
|  6 | system user |                     | NULL | Connect | 6343 | Waiting for master to send event                                            | NULL             |
|  7 | system user |                     | NULL | Connect | 5859 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL             |
|  9 | root        | localhost           | NULL | Query   |    0 | init                                                                        | show processlist |
+----+-------------+---------------------+------+---------+------+-----------------------------------------------------------------------------+------------------+
4 rows in set (0.00 sec)
相關文章
相關標籤/搜索