mysql主從同步原理及應用場景示例詳解
基礎知識
隨著業務復雜度的增加,單臺 MySQL 數據庫服務器已不能滿足實際的需求,取而代之的是數據庫服務器集群。MySQL 具有支持分佈式的特性,能輕松搭建一個支持高並發的 MySQL 數據庫服務器集群。在集群中我們必須保證各個 MySQL 節點的數據是同步的。主從同步就是一種最為常見的同步方式。
主從同步是指,在數據同步過程中,一臺服務器充當主服務器(Master),接收來自用戶的內容更新,另一個或多個其它的服務器充當從服務器(Slave),接收來自主服務器的 binlog 內容,解析出 SQL 語句,更新到從數據庫,使得主從服務器的數據達到一致。
MySQL 主從同步的主要應用場景有:
- 從服務器作為主服務器的備份節點,防止單點災難;
- 後續,可以在主從同步的基礎上,通過一些數據庫中間件實現讀寫分離,從而大幅提高數據庫的並發性能;
- 根據業務將多個從服務器進行拆分,實現專庫專用。
從 MySQL5.6 版本開始,實現主從數據同步有兩種方式:基於日志(binlog)和基於 GTID(全局事務標示符)。
原理
要實現 MySQL 主從同步,首先必須打開 Master 端的 binlog 記錄功能,否則就無法實現。因為整個同步過程實際上就是 Slave 端從 Master 端獲取 binlog 日志,然後再在 Slave 上以相同的順序執行從 binlog 日志中所記錄的各種 SQL,如下圖所示。
主從同步原理:
- 主數據庫中對數據的各種操作,都會自動寫入 Binary Log 中;
- 從數據庫會在一定時間間隔內探測主數據庫的 Binary Log 是否發生變化,如有變化,則開始一個 IO 線程,請求訪問主數據庫的二進制日志文件並保存到從數據庫的中繼日志(Relay Log)中;
- 從數據庫啟動 SQL 線程從中繼日志中讀取二進制日志,在本地重放,使其數據與主數據庫保持一致,完成後相關線程會陷入休眠,等待下一次喚醒。
設置主從同步,還有以下幾個前提:
- 主庫和從庫的版本保持一致;
- 主從同步集群中每個數據庫實例的 server-id 值不能重復;
實驗環境模擬實現主從同步
我們在此使用 docker 這樣的容器技術在一臺主機上實現 mysql 的主從同步。這裡需要做一點解釋,docker 中存在容器的概念,當啟動一個 mysql 容器時,其實可以理解為啟動瞭一臺僅僅隻安裝瞭 mysql 的服務器。
首先在 docker 中拉取 mysql 5.7 版本的鏡像:
docker pull mysql:5.7
使用以下命令,啟動一個 Master 容器,將其命名為 masterMysql
,並設置 mysql 的 root 用戶密碼為 123456:
docker run -p 3339:3306 --name masterMysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
使用以下命令可以查看正在運行的容器:
dokcer ps
這裡可以看到,主容器已經啟動起來瞭。
同樣的方式,啟動一個 Slave 容器,將其命名為 slaveMysql
, 並設置 mysql 的 root 用戶密碼為 123456:
docker run -p 3340:3306 --name slaveMysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
通過以下命令進入到 Master 容器內部:
docker exec -it masterMysql /bin/bash
也可以使用查看正在運行容器時查看到的 CONTAINER ID
來啟動,例如筆者使用這種方式的啟動命令如下:
docker exec -it c30b3528b8c8 /bin/bash
兩種啟動方式都可以。
由於容器環境下沒有安裝 vim
,所以使用以下命令安裝 vim
:
sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list apt update apt install vim
使用以下命令切換到 /etc/mysql
目錄下,修改配置文件 my.cnf
:
cd /etc/mysql vim my.cnf
在 my.cnf
中添加如下配置:
[mysqld] server-id=100 sync-binlog=1 binlog-do-db=world log-bin=mysql-bin
參數說明:
server-id
:即主從集群中每個數據庫實例 id,在多個服務器間該值不能重復,可以設置 1 – 255 之間的任意值。sync-binlog
:該參數控制數據操作與磁盤日志同步頻率。該參數的值 n 表示,執行 n 次寫入後,與磁盤同步一次,示例中設置為 1,是最安全的,但也是最慢的。binlog-do-db
:表示準備進行同步的數據庫。log-bin
:開啟二進制日志功能,可以隨便取
之後使用以下命令重啟 mysql 使配置文件生效。此時,docker 容器也會停止,還需要啟動一次 masterMysql 容器:
service mysql restart
docker start masterMysql docker exec -it masterMysql /bin/bash
接下來,進入數據庫:
mysql -uroot -p123456
在 Master 上配置復制所需要的賬戶,這裡創建一個 slave 用戶, % 表示任何遠程地址的 slave 用戶都可以連接 Master 容器:
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
授予用戶 slave replication slave
權限和 replication client
權限,用於在主從庫之間同步數據:
GRANT replication slave, replication client ON *.* TO 'slave'@'%';
查看二進制日志狀態信息,獲取 position 的值,為從服務器配置做準備:
SHOW MASTER STATUS;
重新開啟一個 Xfce Terminal,通過以下命令進入到 Slave 容器內部:
docker exec -it slaveMysql /bin/bash
由於容器環境下沒有安裝 vim
,所以使用以下命令安裝 vim
:
sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list apt update apt install vim
使用以下命令切換到 /etc/mysql
目錄下,修改配置文件 my.cnf
:
cd /etc/mysql vim my.cnf
在 my.cnf
中添加如下配置:
[mysqld] server-id=101 log-bin=mysql-slave-bin relay_log=edu-mysql-relay-bin
參數說明:
log-bin
:開啟二進制日志功能,以備 Slave 作為其它 Slave 的 Master 時使用relay_log
:配置中繼日志
之後使用以下命令重啟 mysql 使配置文件生效。
service mysql restart
docker start slaveMysql docker exec -it slaveMysql /bin/bash
進入 MySQL:
mysql -uroot -p123456
接下來執行以下命令:
change master to master_host='172.17.0.2', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 617, master_connect_retry=30;
參數說明:
master_host
:Master 的地址,指的是容器的獨立 IP,可以通過docker inspect --format='{{.NetworkSettings.IPAddress}}' masterMysql
查詢 Master 的 IP
master_user
:Master 中設置的用戶名
master_password
:Master 中設置的用戶名對應密碼
master_port
: Master 的端口號,指的是容器的端口號
master_log_file
:二進制日志文件名(這裡註意填寫為實驗者在之前使用 show master status
命令查詢出來的值)
master_log_pos
:二進制日志的 position 值(這裡註意填寫為實驗者在之前使用 show master status
命令查詢出來的值)
master_connect_retry
:如果連接失敗,重試的時間間隔,單位是秒,默認是 60 秒
執行以下命令,啟動主從操作:
start slave;
執行以下命令,查詢 Slave 狀態:
show slave status\G
結果如下:
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.2
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 617
Relay_Log_File: edu-mysql-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
…
我們主要查看的是 Slave_IO_Running 和 Slave_SQL_Running ,如果它們的值都是 Yes,則表示主從環境配置成功。
測試主從復制就比較簡單瞭,我們仿照之前的實驗,在 Master 中新建一個 world 數據庫,然後插入一些數據:
CREATE DATABASE world; USE world; CREATE TABLE student( stuId INT(10) NOT NULL, stuName VARCHAR(10) NOT NULL, stuAge INT(10) NOT NULL, PRIMARY KEY(stuId) ); INSERT INTO student(stuId, stuName, stuAge) VALUES(1, 'zhangsan', 18),(2, 'lisi', 19), (3, 'wangwu', 18);
在 Slave 中執行:
SHOW DATABASES;
可以看到我們在 Master 中新建的 world 數據庫已經同步過來瞭。
再執行以下命令查看插入的數據是否也同步過來瞭:
USE world; SELECT * FROM student;
可以看到插入的數據也已經同步過來瞭。
接下來再在 Master 刪除一條數據:
DELETE FROM student WHERE stuId = 1;
再在 Slave 中執行以下命令查看數據是否同步成功:
SELECT * FROM student;
此時主從復制情況良好。
以上就是mysql主從同步原理及應用場景示例詳解的詳細內容,更多關於mysql主從同步的資料請關註WalkonNet其它相關文章!