MySQL 主從一直是面試??停锩娴闹R(shí)點(diǎn)雖然基礎(chǔ),但是能回答全的同學(xué)不多。
創(chuàng)新互聯(lián)建站是專業(yè)的朝陽(yáng)網(wǎng)站建設(shè)公司,朝陽(yáng)接單;提供網(wǎng)站制作、成都網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行朝陽(yáng)網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
比如樓哥之前面試小米,就被問(wèn)到過(guò)主從復(fù)制的原理,以及主從延遲的解決方案,因?yàn)榛卮鸬姆浅2诲e(cuò),給面試官留下非常好的印象。你之前面試,有遇到過(guò)哪些 MySQL 主從的問(wèn)題呢?
所謂 MySQL 主從,就是建立兩個(gè)完全一樣的數(shù)據(jù)庫(kù),一個(gè)是主庫(kù),一個(gè)是從庫(kù), 主庫(kù)對(duì)外提供讀寫(xiě)的操作,從庫(kù)對(duì)外提供讀的操作 ,下面是一主一從模式:
對(duì)于數(shù)據(jù)庫(kù)單機(jī)部署,在 4 核 8G 的機(jī)器上運(yùn)行 MySQL 5.7 時(shí),大概可以支撐 500 的 TPS 和 10000 的 QPS, 當(dāng)遇到一些活動(dòng)時(shí),查詢流量驟然,就需要進(jìn)行主從分離。
大部分系統(tǒng)的訪問(wèn)模型是讀多寫(xiě)少,讀寫(xiě)請(qǐng)求量的差距可能達(dá)到幾個(gè)數(shù)量級(jí),所以我們可以通過(guò)一主多從的方式, 主庫(kù)只負(fù)責(zé)寫(xiě)入和部分核心邏輯的查詢,多個(gè)從庫(kù)只負(fù)責(zé)查詢,提升查詢性能,降低主庫(kù)壓力。
MySQL 主從還能做到服務(wù)高可用,當(dāng)主庫(kù)宕機(jī)時(shí),從庫(kù)可以切成主庫(kù),保證服務(wù)的高可用,然后主庫(kù)也可以做數(shù)據(jù)的容災(zāi)備份。
整體場(chǎng)景總結(jié)如下:
MySQL 的主從復(fù)制是依賴于 binlog 的,也就是記錄 MySQL 上的所有變化并以二進(jìn)制形式保存在磁盤(pán)上二進(jìn)制日志文件。
主從復(fù)制就是將 binlog 中的數(shù)據(jù)從主庫(kù)傳輸?shù)綇膸?kù)上,一般這個(gè)過(guò)程是異步的,即主庫(kù)上的操作不會(huì)等待 binlog 同步的完成。
詳細(xì)流程如下:
當(dāng)主庫(kù)和從庫(kù)數(shù)據(jù)同步時(shí),突然中斷怎么辦?因?yàn)橹鲙?kù)與從庫(kù)之間維持了一個(gè)長(zhǎng)鏈接,主庫(kù)內(nèi)部有一個(gè)線程,專門(mén)服務(wù)于從庫(kù)的這個(gè)長(zhǎng)鏈接的。
對(duì)于下面的情況,假如主庫(kù)執(zhí)行如下 SQL,其中 a 和 create_time 都是索引:
我們知道,數(shù)據(jù)選擇了 a 索引和選擇 create_time 索引,最后 limit 1 出來(lái)的數(shù)據(jù)一般是不一樣的。
所以就會(huì)存在這種情況:在 binlog = statement 格式時(shí),主庫(kù)在執(zhí)行這條 SQL 時(shí),使用的是索引 a,而從庫(kù)在執(zhí)行這條 SQL 時(shí),使用了索引 create_time,最后主從數(shù)據(jù)不一致了。
那么我們改如何解決呢?
可以把 binlog 格式修改為 row,row 格式的 binlog 日志記錄的不是 SQL 原文,而是兩個(gè) event:Table_map 和 Delete_rows。
Table_map event 說(shuō)明要操作的表,Delete_rows event用于定義要?jiǎng)h除的行為,記錄刪除的具體行數(shù)。 row 格式的 binlog 記錄的就是要?jiǎng)h除的主鍵 ID 信息,因此不會(huì)出現(xiàn)主從不一致的問(wèn)題。
但是如果 SQL 刪除 10 萬(wàn)行數(shù)據(jù),使用 row 格式就會(huì)很占空間的,10 萬(wàn)條數(shù)據(jù)都在 binlog 里面,寫(xiě) binlog 的時(shí)候也很耗 IO。但是 statement 格式的 binlog 可能會(huì)導(dǎo)致數(shù)據(jù)不一致。
設(shè)計(jì) MySQL 的大叔想了一個(gè)折中的方案,mixed 格式的 binlog,其實(shí)就是 row 和 statement 格式混合使用, 當(dāng) MySQL 判斷可能數(shù)據(jù)不一致時(shí),就用 row 格式,否則使用就用 statement 格式。
有時(shí)候我們遇到從數(shù)據(jù)庫(kù)中獲取不到信息的詭異問(wèn)題時(shí),會(huì)糾結(jié)于代碼中是否有一些邏輯會(huì)把之前寫(xiě)入的內(nèi)容刪除,但是你又會(huì)發(fā)現(xiàn),過(guò)了一段時(shí)間再去查詢時(shí)又可以讀到數(shù)據(jù)了,這基本上就是主從延遲在作怪。
主從延遲,其實(shí)就是“從庫(kù)回放” 完成的時(shí)間,與 “主庫(kù)寫(xiě) binlog” 完成時(shí)間的差值, 會(huì)導(dǎo)致從庫(kù)查詢的數(shù)據(jù),和主庫(kù)的不一致 。
談到 MySQL 數(shù)據(jù)庫(kù)主從同步延遲原理,得從 MySQL 的主從復(fù)制原理說(shuō)起:
總結(jié)一下主從延遲的主要原因 :主從延遲主要是出現(xiàn)在 “relay log 回放” 這一步,當(dāng)主庫(kù)的 TPS 并發(fā)較高,產(chǎn)生的 DDL 數(shù)量超過(guò)從庫(kù)一個(gè) SQL 線程所能承受的范圍,那么延時(shí)就產(chǎn)生了,當(dāng)然還有就是可能與從庫(kù)的大型 query 語(yǔ)句產(chǎn)生了鎖等待。
我們一般會(huì)把從庫(kù)落后的時(shí)間作為一個(gè)重點(diǎn)的數(shù)據(jù)庫(kù)指標(biāo)做監(jiān)控和報(bào)警,正常的時(shí)間是在毫秒級(jí)別,一旦落后的時(shí)間達(dá)到了秒級(jí)別就需要告警了。
解決該問(wèn)題的方法,除了縮短主從延遲的時(shí)間,還有一些其它的方法,基本原理都是盡量不查詢從庫(kù)。
具體解決方案如下:
在實(shí)際應(yīng)用場(chǎng)景中,對(duì)于一些非常核心的場(chǎng)景,比如庫(kù)存,支付訂單等,需要直接查詢從庫(kù),其它非核心場(chǎng)景,就不要去查主庫(kù)了。
兩臺(tái)機(jī)器 A 和 B,A 為主庫(kù),負(fù)責(zé)讀寫(xiě),B 為從庫(kù),負(fù)責(zé)讀數(shù)據(jù)。
如果 A 庫(kù)發(fā)生故障,B 庫(kù)成為主庫(kù)負(fù)責(zé)讀寫(xiě),修復(fù)故障后,A 成為從庫(kù),主庫(kù) B 同步數(shù)據(jù)到從庫(kù) A。
一臺(tái)主庫(kù)多臺(tái)從庫(kù),A 為主庫(kù),負(fù)責(zé)讀寫(xiě),B、C、D為從庫(kù),負(fù)責(zé)讀數(shù)據(jù)。
如果 A 庫(kù)發(fā)生故障,B 庫(kù)成為主庫(kù)負(fù)責(zé)讀寫(xiě),C、D負(fù)責(zé)讀,修復(fù)故障后,A 也成為從庫(kù),主庫(kù) B 同步數(shù)據(jù)到從庫(kù) A。
1、建立賬號(hào)
進(jìn)入mysql數(shù)據(jù)庫(kù),創(chuàng)建一個(gè)用于從庫(kù)備份的賬號(hào)
mysqlGRANT REPLICATION SLAVE ON *.* TO 'slave_test'@'10.19.194.57' IDENTIFIED BY 'Password@123456';
mysqlFLUSH PRIVILEGES; ? ---刷新
該命令詳情參考grant創(chuàng)建用戶命令
2、如果已經(jīng)有一個(gè)實(shí)例在運(yùn)行(因?yàn)殚_(kāi)始已經(jīng)安裝了mysql,所以有一個(gè)默認(rèn)的),那么再啟動(dòng)一個(gè)實(shí)例,方法如下:
(1)shellcd /usr/local/mysql/
(2)shellmkdir -pv /data/mysql2
(3)shellchown -R mysql.mysql /data/mysql2
(4)shell./scripts/mysql_install_db ?--user=mysql??--datadir=/data/mysql2 ?這個(gè)為另外一個(gè)目錄,該步驟意味初始化目錄,并創(chuàng)建一個(gè)實(shí)例
3、配置/etc/my點(diǎn)吸煙 f,配置方法如下
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
user = root
[mysqld] ## 本來(lái)mysql配置
server-id = 1
port = 3306
socket = /data/mysql/mysql.sock
datadir = /data/mysql
pid-file = /data/mysql/wzj.pid
log-error = /data/mysql/wzj.err
log-bin = /data/mysql/log/bin-log
log-bin-index = /data/mysql/log/mysql-bin.index
user = mysql
[mysqld2] ?##創(chuàng)建實(shí)例配置
server-id = 2
port = 3307
socket = /tmp/mysql2.sock
datadir = /data/mysql2/ ? ? ? ? ? ? ? ? ? ? ? ? //mysql2存儲(chǔ)數(shù)據(jù)庫(kù)的地方,也就是實(shí)例
pid-file = /data/mysql2/mysql2.pid ? ? ? //mysql2的pid文件記錄
log-error = /data/mysql2/mysql2.err ? ? //為錯(cuò)誤日志文件的地方
user = mysql
#master-host =10.19.194.57
#master-user ='wzj_slave_test'
#master-pass ='Password@123456'
#master-port =3306
#master_connect_retry=60
#replicate-do-db =mysql_wzj
#replicate-ignore-db=mysql--------該段已注釋,因?yàn)樾掳姹局?,需要用CHANGE MASTER TO 命令去設(shè)置
【注意】:以上文件的目錄,皆為系統(tǒng)創(chuàng)建,并非手動(dòng)去創(chuàng)建,設(shè)置配置文件后,重啟mysql,文件就會(huì)自動(dòng)創(chuàng)建
4、重啟,然后可以使用msyql_multi命令啟動(dòng)實(shí)例,再查看一下master主庫(kù)的狀態(tài),其中Binlog_Do_DB表示要備份的數(shù)據(jù)庫(kù),Binlog_Ignore_DB表示不備份的數(shù)據(jù)庫(kù)
shell/etc/rc.d/init.d/mysqld start/stop/restart
shell/usr/local/mysql/bin/mysqld_multi start 1-2 ?啟動(dòng)實(shí)例 (1-2表示啟動(dòng)1、2兩個(gè)實(shí)例)
shellmysql master: mysql -P 3306 -u root -p -S /data/mysql/mysql.sock (密碼:1)
mysqlshow master status; or show master status \G; ? 顯示主庫(kù)的狀態(tài),其中File 和Position 數(shù)值要記住,下面的mysql語(yǔ)句要用到,用于設(shè)置從庫(kù)
5、進(jìn)入從庫(kù),并設(shè)置從庫(kù)的一些參數(shù)
shellslave:mysql -P 3307 -u root -p -S /tmp/mysql2.sock (密碼:回車(chē)) ??---另外開(kāi)個(gè)遠(yuǎn)程
mysqlCHANGE MASTER TO
mysql MASTER_HOST='10.19.194.57', ?---主庫(kù)的地址
mysqlMASTER_USER='wzj_slave_test', ?---主庫(kù)用戶
mysqlMASTER_PASSWORD='Password@123456', ? ---主庫(kù)的密碼
mysqlMASTER_LOG_FILE='bin-log.000013' , ?---此參數(shù)為master status中的File值
mysqlMASTER_LOG_POS=120; ? ---此數(shù)值為Position數(shù)值
6、設(shè)置好后,運(yùn)行start slave,如果下圖紅線地方是YES,則成功,否則,查看配置文件是否有錯(cuò)或有誤。
slave_io_running ?:yes
slave_sql_running :yes
7、可以查看從庫(kù)下mysql進(jìn)程信息
mysqlshow processlist;
8、測(cè)試
在主庫(kù)上面建新的數(shù)據(jù)庫(kù),然后在從庫(kù)中查看是否有同步~
1.在主數(shù)據(jù)庫(kù)服務(wù)器為從服務(wù)器添加一個(gè)擁有權(quán)限訪問(wèn)主庫(kù)的用戶:
GRANT REPLICATION SLAVE ON *.* TO ' test'@'%' IDENTIFIED BY 'test';
(%表示允許所有IP,可設(shè)置指定從服務(wù)器IP)
添加用戶后:
可在從服務(wù)器上用mysql -h127.0.0.1 -utest -ptest; 來(lái)測(cè)試是否有權(quán)限訪問(wèn)主數(shù)據(jù)庫(kù)
2.在主據(jù)庫(kù)配置文件加上:
#master config
server-id = 1
log-bin = mysql-bin
3.在從服務(wù)器數(shù)據(jù)庫(kù)配置文件:
server-id = 2
master-host = 10.0.0.199
master-user = test
master-password = test
replicate-do-db = test
master-port = 3306
log-bin = mysql-bin
如果你的一切配置順利
你在從服務(wù)器上輸入命令:show slave status\G
成功情況:
Slave_IO_Running:yes
Slave_SQL_Running:yes
在主服務(wù)器上輸入show master status
網(wǎng)站名稱:mysql怎么主庫(kù)關(guān)從庫(kù) mysql主庫(kù)從庫(kù)配置
本文URL:http://chinadenli.net/article30/ddeijso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷(xiāo)、虛擬主機(jī)、自適應(yīng)網(wǎng)站、品牌網(wǎng)站建設(shè)、企業(yè)建站、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)