mysql主從同步原理及應(yīng)用場(chǎng)景示例詳解
基礎(chǔ)知識(shí)
隨著業(yè)務(wù)復(fù)雜度的增加,單臺(tái) MySQL 數(shù)據(jù)庫(kù)服務(wù)器已不能滿(mǎn)足實(shí)際的需求,取而代之的是數(shù)據(jù)庫(kù)服務(wù)器集群。MySQL 具有支持分布式的特性,能輕松搭建一個(gè)支持高并發(fā)的 MySQL 數(shù)據(jù)庫(kù)服務(wù)器集群。在集群中我們必須保證各個(gè) MySQL 節(jié)點(diǎn)的數(shù)據(jù)是同步的。主從同步就是一種最為常見(jiàn)的同步方式。
主從同步是指,在數(shù)據(jù)同步過(guò)程中,一臺(tái)服務(wù)器充當(dāng)主服務(wù)器(Master),接收來(lái)自用戶(hù)的內(nèi)容更新,另一個(gè)或多個(gè)其它的服務(wù)器充當(dāng)從服務(wù)器(Slave),接收來(lái)自主服務(wù)器的 binlog 內(nèi)容,解析出 SQL 語(yǔ)句,更新到從數(shù)據(jù)庫(kù),使得主從服務(wù)器的數(shù)據(jù)達(dá)到一致。
MySQL 主從同步的主要應(yīng)用場(chǎng)景有:
- 從服務(wù)器作為主服務(wù)器的備份節(jié)點(diǎn),防止單點(diǎn)災(zāi)難;
- 后續(xù),可以在主從同步的基礎(chǔ)上,通過(guò)一些數(shù)據(jù)庫(kù)中間件實(shí)現(xiàn)讀寫(xiě)分離,從而大幅提高數(shù)據(jù)庫(kù)的并發(fā)性能;
- 根據(jù)業(yè)務(wù)將多個(gè)從服務(wù)器進(jìn)行拆分,實(shí)現(xiàn)專(zhuān)庫(kù)專(zhuān)用。
從 MySQL5.6 版本開(kāi)始,實(shí)現(xiàn)主從數(shù)據(jù)同步有兩種方式:基于日志(binlog)和基于 GTID(全局事務(wù)標(biāo)示符)。
原理
要實(shí)現(xiàn) MySQL 主從同步,首先必須打開(kāi) Master 端的 binlog 記錄功能,否則就無(wú)法實(shí)現(xiàn)。因?yàn)檎麄€(gè)同步過(guò)程實(shí)際上就是 Slave 端從 Master 端獲取 binlog 日志,然后再在 Slave 上以相同的順序執(zhí)行從 binlog 日志中所記錄的各種 SQL,如下圖所示。

主從同步原理:
- 主數(shù)據(jù)庫(kù)中對(duì)數(shù)據(jù)的各種操作,都會(huì)自動(dòng)寫(xiě)入 Binary Log 中;
- 從數(shù)據(jù)庫(kù)會(huì)在一定時(shí)間間隔內(nèi)探測(cè)主數(shù)據(jù)庫(kù)的 Binary Log 是否發(fā)生變化,如有變化,則開(kāi)始一個(gè) IO 線程,請(qǐng)求訪問(wèn)主數(shù)據(jù)庫(kù)的二進(jìn)制日志文件并保存到從數(shù)據(jù)庫(kù)的中繼日志(Relay Log)中;
- 從數(shù)據(jù)庫(kù)啟動(dòng) SQL 線程從中繼日志中讀取二進(jìn)制日志,在本地重放,使其數(shù)據(jù)與主數(shù)據(jù)庫(kù)保持一致,完成后相關(guān)線程會(huì)陷入休眠,等待下一次喚醒。
設(shè)置主從同步,還有以下幾個(gè)前提:
- 主庫(kù)和從庫(kù)的版本保持一致;
- 主從同步集群中每個(gè)數(shù)據(jù)庫(kù)實(shí)例的 server-id 值不能重復(fù);
實(shí)驗(yàn)環(huán)境模擬實(shí)現(xiàn)主從同步
我們?cè)诖耸褂?docker 這樣的容器技術(shù)在一臺(tái)主機(jī)上實(shí)現(xiàn) mysql 的主從同步。這里需要做一點(diǎn)解釋?zhuān)琩ocker 中存在容器的概念,當(dāng)啟動(dòng)一個(gè) mysql 容器時(shí),其實(shí)可以理解為啟動(dòng)了一臺(tái)僅僅只安裝了 mysql 的服務(wù)器。
首先在 docker 中拉取 mysql 5.7 版本的鏡像:
docker pull mysql:5.7
使用以下命令,啟動(dòng)一個(gè) Master 容器,將其命名為 masterMysql,并設(shè)置 mysql 的 root 用戶(hù)密碼為 123456:
docker run -p 3339:3306 --name masterMysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
使用以下命令可以查看正在運(yùn)行的容器:
dokcer ps

這里可以看到,主容器已經(jīng)啟動(dòng)起來(lái)了。
同樣的方式,啟動(dòng)一個(gè) Slave 容器,將其命名為 slaveMysql, 并設(shè)置 mysql 的 root 用戶(hù)密碼為 123456:
docker run -p 3340:3306 --name slaveMysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
通過(guò)以下命令進(jìn)入到 Master 容器內(nèi)部:
docker exec -it masterMysql /bin/bash

也可以使用查看正在運(yùn)行容器時(shí)查看到的 CONTAINER ID 來(lái)啟動(dòng),例如筆者使用這種方式的啟動(dòng)命令如下:
docker exec -it c30b3528b8c8 /bin/bash
兩種啟動(dòng)方式都可以。
由于容器環(huán)境下沒(méi)有安裝 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
參數(shù)說(shuō)明:
server-id:即主從集群中每個(gè)數(shù)據(jù)庫(kù)實(shí)例 id,在多個(gè)服務(wù)器間該值不能重復(fù),可以設(shè)置 1 - 255 之間的任意值。sync-binlog:該參數(shù)控制數(shù)據(jù)操作與磁盤(pán)日志同步頻率。該參數(shù)的值 n 表示,執(zhí)行 n 次寫(xiě)入后,與磁盤(pán)同步一次,示例中設(shè)置為 1,是最安全的,但也是最慢的。binlog-do-db:表示準(zhǔn)備進(jìn)行同步的數(shù)據(jù)庫(kù)。log-bin:開(kāi)啟二進(jìn)制日志功能,可以隨便取
之后使用以下命令重啟 mysql 使配置文件生效。此時(shí),docker 容器也會(huì)停止,還需要啟動(dòng)一次 masterMysql 容器:
service mysql restart
docker start masterMysql docker exec -it masterMysql /bin/bash

接下來(lái),進(jìn)入數(shù)據(jù)庫(kù):
mysql -uroot -p123456
在 Master 上配置復(fù)制所需要的賬戶(hù),這里創(chuàng)建一個(gè) slave 用戶(hù), % 表示任何遠(yuǎn)程地址的 slave 用戶(hù)都可以連接 Master 容器:
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
授予用戶(hù) slave replication slave 權(quán)限和 replication client 權(quán)限,用于在主從庫(kù)之間同步數(shù)據(jù):
GRANT replication slave, replication client ON *.* TO 'slave'@'%';

查看二進(jìn)制日志狀態(tài)信息,獲取 position 的值,為從服務(wù)器配置做準(zhǔn)備:
SHOW MASTER STATUS;

重新開(kāi)啟一個(gè) Xfce Terminal,通過(guò)以下命令進(jìn)入到 Slave 容器內(nèi)部:
docker exec -it slaveMysql /bin/bash

由于容器環(huán)境下沒(méi)有安裝 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
參數(shù)說(shuō)明:
log-bin:開(kāi)啟二進(jìn)制日志功能,以備 Slave 作為其它 Slave 的 Master 時(shí)使用relay_log:配置中繼日志
之后使用以下命令重啟 mysql 使配置文件生效。
service mysql restart
docker start slaveMysql docker exec -it slaveMysql /bin/bash
進(jìn)入 MySQL:
mysql -uroot -p123456
接下來(lái)執(zhí)行以下命令:
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;

參數(shù)說(shuō)明:
master_host:Master 的地址,指的是容器的獨(dú)立 IP,可以通過(guò)docker inspect --format='{{.NetworkSettings.IPAddress}}' masterMysql 查詢(xún) Master 的 IP
master_user:Master 中設(shè)置的用戶(hù)名
master_password:Master 中設(shè)置的用戶(hù)名對(duì)應(yīng)密碼
master_port: Master 的端口號(hào),指的是容器的端口號(hào)
master_log_file:二進(jìn)制日志文件名(這里注意填寫(xiě)為實(shí)驗(yàn)者在之前使用 show master status 命令查詢(xún)出來(lái)的值)
master_log_pos:二進(jìn)制日志的 position 值(這里注意填寫(xiě)為實(shí)驗(yàn)者在之前使用 show master status 命令查詢(xún)出來(lái)的值)
master_connect_retry:如果連接失敗,重試的時(shí)間間隔,單位是秒,默認(rèn)是 60 秒
執(zhí)行以下命令,啟動(dòng)主從操作:
start slave;
執(zhí)行以下命令,查詢(xún) Slave 狀態(tài):
show slave status\G
結(jié)果如下:
*************************** 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,則表示主從環(huán)境配置成功。
測(cè)試主從復(fù)制就比較簡(jiǎn)單了,我們仿照之前的實(shí)驗(yàn),在 Master 中新建一個(gè) world 數(shù)據(jù)庫(kù),然后插入一些數(shù)據(jù):
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 中執(zhí)行:
SHOW DATABASES;

可以看到我們?cè)?Master 中新建的 world 數(shù)據(jù)庫(kù)已經(jīng)同步過(guò)來(lái)了。
再執(zhí)行以下命令查看插入的數(shù)據(jù)是否也同步過(guò)來(lái)了:
USE world; SELECT * FROM student;

可以看到插入的數(shù)據(jù)也已經(jīng)同步過(guò)來(lái)了。
接下來(lái)再在 Master 刪除一條數(shù)據(jù):
DELETE FROM student WHERE stuId = 1;
再在 Slave 中執(zhí)行以下命令查看數(shù)據(jù)是否同步成功:
SELECT * FROM student;

此時(shí)主從復(fù)制情況良好。
以上就是mysql主從同步原理及應(yīng)用場(chǎng)景示例詳解的詳細(xì)內(nèi)容,更多關(guān)于mysql主從同步的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySQL中B樹(shù)索引和B+樹(shù)索引的區(qū)別詳解
這篇文章主要為大家詳細(xì)介紹了MySQL中B樹(shù)索引和B+樹(shù)索引的區(qū)別,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
mysql 數(shù)據(jù)庫(kù)中my.ini的優(yōu)化 2G內(nèi)存針對(duì)站多 抗壓型的設(shè)置
MySQL數(shù)據(jù)庫(kù)之?dāng)?shù)據(jù)表操作DDL數(shù)據(jù)定義語(yǔ)言
windows中同時(shí)安裝兩個(gè)不同版本的mysql數(shù)據(jù)庫(kù)
mysql 8.0.15 winx64壓縮包安裝配置方法圖文教程

