- 數(shù)據(jù)生態(tài):MySQL復(fù)制技術(shù)與生產(chǎn)實(shí)踐
- 羅小波
- 2219字
- 2020-11-24 13:04:59
第2章 復(fù)制的基本原理
第1章簡單介紹了MySQL復(fù)制(技術(shù))相關(guān)的基本概念,本章將詳細(xì)介紹其基本原理。MySQL的復(fù)制技術(shù)自誕生以來,隨著各種各樣的應(yīng)用場景對數(shù)據(jù)安全性及復(fù)制性能的要求不斷提高,也在不斷迭代與優(yōu)化。要深刻理解MySQL的復(fù)制技術(shù),就要從它的基本原理說起[1],下面將對此展開介紹。
2.1 概述
復(fù)制是基于主庫(master)二進(jìn)制日志中寫入的關(guān)于該數(shù)據(jù)庫的所有更改(更新、刪除等)的日志記錄來實(shí)現(xiàn)的。從庫(slave)利用這些二進(jìn)制日志中的事件記錄進(jìn)行回放來同步數(shù)據(jù)。但對于不修改任何數(shù)據(jù)的查詢語句,主庫不會(huì)記錄二進(jìn)制日志(例如SELECT語句),所以,對于查詢語句,從庫自然也沒有需要回放的內(nèi)容。
連接到主庫的每個(gè)從庫都會(huì)復(fù)制一份主庫二進(jìn)制日志的副本。從庫利用來自主庫的二進(jìn)制日志進(jìn)行回放,就可以模擬主庫中的數(shù)據(jù)變更操作,例如,建表、修改表結(jié)構(gòu)等DDL(Data Definition Language,數(shù)據(jù)定義語言)操作以及DML(Data Manipulation Language,數(shù)據(jù)操縱語言)操作。
提示:對于主庫中的二進(jìn)制日志同步到從庫時(shí)發(fā)起請求的方向,在此有必要做一些說明。二進(jìn)制日志的同步,既有從庫主動(dòng)請求的情況,也有主庫主動(dòng)推送的情況。
? 對于復(fù)制線程在主從之間新建立連接或重新建立連接的情況,不是主庫主動(dòng)推送二進(jìn)制日志(因?yàn)檫@時(shí)主庫并不知道需要發(fā)送哪些二進(jìn)制日志給新建立連接的從庫),而是從庫主動(dòng)向主庫請求所需的二進(jìn)制日志(從庫向主庫注冊連接時(shí),攜帶了從庫自身所需二進(jìn)制日志的位置信息)。主從之間的復(fù)制連接始終是從庫先發(fā)起請求的,就算主庫主動(dòng)斷開了從庫的連接,重新建立連接時(shí)也是從庫重試的,而不是主庫。
? 如果復(fù)制線程已經(jīng)在主從之間建立連接,而且從庫已經(jīng)完全接收建立連接時(shí)請求的二進(jìn)制日志內(nèi)容,后續(xù)的增量二進(jìn)制日志是由主庫主動(dòng)推送給從庫的,而不是從庫主動(dòng)向主庫請求的(因?yàn)檫@時(shí)主庫隨時(shí)都可能寫入新的內(nèi)容,從庫難以即時(shí)感知,也沒必要即時(shí)感知)。例如,主庫在某段時(shí)間內(nèi)沒有寫入任何數(shù)據(jù),從庫已經(jīng)完全接收了最新的二進(jìn)制日志內(nèi)容,當(dāng)主庫再次寫入新的數(shù)據(jù)時(shí)產(chǎn)生的新二進(jìn)制日志,主庫會(huì)直接發(fā)送給從庫,而不需要發(fā)送一個(gè)通知給從庫I/O線程,然后讓從庫來拉取(主庫在產(chǎn)生新的二進(jìn)制日志時(shí),只會(huì)通知主庫自身的Binlog Dump線程,而不會(huì)通知從庫I/O線程,當(dāng)主庫的Binlog Dump線程收到通知之后,會(huì)直接把新產(chǎn)生的二進(jìn)制日志發(fā)送給從庫I/O線程)。
每個(gè)從庫的復(fù)制操作都是獨(dú)立運(yùn)行的,即每個(gè)從庫對從主庫拉取的二進(jìn)制日志的回放都是獨(dú)立發(fā)生的,互不影響。每個(gè)從庫都按照自己的進(jìn)度讀取主庫二進(jìn)制日志(從主庫中同步的二進(jìn)制日志保存在每個(gè)從庫自身的中繼日志中)并進(jìn)行回放來更新自身的數(shù)據(jù),而且每個(gè)從庫都可以獨(dú)立地隨意啟動(dòng)/停止自己的I/O線程和SQL線程。
主庫和從庫都會(huì)定期輸出在復(fù)制過程中的狀態(tài),可以通過相關(guān)的復(fù)制狀態(tài)變量來監(jiān)控這些狀態(tài)的變化。從庫在進(jìn)行回放之前,會(huì)先將從主庫接收的二進(jìn)制日志寫入本地的中繼日志,中繼日志中還記錄了主庫二進(jìn)制日志文件位置的有關(guān)信息。
2.2 細(xì)節(jié)
MySQL的復(fù)制功能用三個(gè)線程來實(shí)現(xiàn):一個(gè)線程在主庫上(Binlog Dump線程),兩個(gè)線程在從庫上(I/O線程和SQL線程),如圖2-1所示。

圖2-1
結(jié)合圖2-1從左往右看,復(fù)制的原理大致如下:
(1)用戶提交對數(shù)據(jù)的修改,然后Master(主庫)把所有數(shù)據(jù)庫變更寫進(jìn)Binary Log(二進(jìn)制日志),主庫通過Binlog Dump 線程把二進(jìn)制日志內(nèi)容推送給Slave(從庫),從庫被動(dòng)接收數(shù)據(jù),不是主動(dòng)去獲取,除非是新建連接。
? 當(dāng)從庫正常連接到主庫時(shí),在主庫中使用SHOW PROCESSLIST語句可以查看到標(biāo)識為“Binlog Dump”的線程。
? Binlog Dump線程在讀取二進(jìn)制日志中要發(fā)送到從庫的每個(gè)事件時(shí),會(huì)獲取二進(jìn)制日志上的鎖。一旦讀取完事件,即使事件還未發(fā)送到從庫,二進(jìn)制日志上的鎖也會(huì)被釋放。
(2)在從庫上執(zhí)行START SLAVE語句時(shí),已經(jīng)使用CHANGE MASTER TO語句配置好復(fù)制信息,從庫會(huì)創(chuàng)建一個(gè)I/O線程,該線程連接到主庫并請求主庫為其發(fā)送所需的二進(jìn)制日志(從庫向主庫注冊連接時(shí),里面攜帶了請求的二進(jìn)制日志的位置,該位置表示從庫所請求的二進(jìn)制日志的起點(diǎn))。
? 從庫I/O線程與主庫的Binlog Dump線程成功建立連接之后,從庫I/O線程接收主庫Binlog Dump線程發(fā)送的二進(jìn)制日志,并將它們寫入從庫本地的Relay Log(中繼日志文件)。
? I/O線程的狀態(tài)可以通過SHOW SLAVE STATUS語句輸出的Slave_IO_running字段值來查看,或者通過SHOW STATUS語句輸出的Slave_running狀態(tài)變量查看(該狀態(tài)變量在MySQL 5.7中已棄用,MySQL 8.0已將其移除)。
(3)從庫SQL線程讀取并解析中繼日志中的內(nèi)容,按照讀取的順序進(jìn)行回放(二進(jìn)制日志中存放的事務(wù)順序就是主庫中事務(wù)的提交順序),并將數(shù)據(jù)變更寫入本地?cái)?shù)據(jù)庫文件中,這樣就實(shí)現(xiàn)了數(shù)據(jù)在主從數(shù)據(jù)庫(實(shí)例)之間的同步。
每一對主從關(guān)系中,都有三個(gè)線程。主庫可以連接多個(gè)從庫,而且會(huì)為每一個(gè)連接成功的從庫創(chuàng)建一個(gè)Binlog Dump線程;從庫也可以連接多個(gè)主庫(多源復(fù)制),而且會(huì)為每一個(gè)連接成功的主庫創(chuàng)建自己的I/O線程和SQL線程。
從庫使用兩個(gè)線程分別將主庫的二進(jìn)制日志讀取到本地,并應(yīng)用這些日志以實(shí)現(xiàn)主從之間的數(shù)據(jù)同步。因此,即便SQL線程執(zhí)行語句緩慢,也不會(huì)影響I/O線程讀取日志的速度(正常情況下,I/O線程不會(huì)成為性能瓶頸,除非網(wǎng)絡(luò)出現(xiàn)問題)。如果SQL線程已經(jīng)應(yīng)用完所有的中繼日志,就表明I/O線程已經(jīng)獲取了主庫中所有的二進(jìn)制日志。
SHOW PROCESSLIST語句提供的信息可以告訴你主庫和從庫上有關(guān)復(fù)制的一些狀態(tài),如下所示:

關(guān)于查看復(fù)制狀態(tài)的更完整的介紹,見第9章“通過PERFORMANCE_SCHEMA庫檢查復(fù)制信息”和第10章“通過其他方式檢查復(fù)制信息”。
[1]注:從MySQL 5.7開始,支持能夠兼顧數(shù)據(jù)一致性和數(shù)據(jù)庫高可用性的組復(fù)制拓?fù)洌捎诒緯粐@主從復(fù)制拓?fù)湔归_,所以后續(xù)提及的“復(fù)制技術(shù)”僅針對“主從復(fù)制拓?fù)洹薄?/p>
- Learning LibGDX Game Development(Second Edition)
- Rust實(shí)戰(zhàn)
- Python進(jìn)階編程:編寫更高效、優(yōu)雅的Python代碼
- Python程序設(shè)計(jì)
- 愛上micro:bit
- Java EE企業(yè)級應(yīng)用開發(fā)教程(Spring+Spring MVC+MyBatis)
- JavaScript動(dòng)態(tài)網(wǎng)頁編程
- Java編程從入門到精通
- Serverless Web Applications with React and Firebase
- 一步一步跟我學(xué)Scratch3.0案例
- Java Hibernate Cookbook
- Learning Kotlin by building Android Applications
- Oracle Database XE 11gR2 Jump Start Guide
- 深入大型數(shù)據(jù)集:并行與分布化Python代碼
- 前端架構(gòu)設(shè)計(jì)