復(fù)制概念
- Mysql內(nèi)建的復(fù)制功能是構(gòu)建大型,高性能應(yīng)用程序的基礎(chǔ)。
- 將Mysql的數(shù)據(jù)分布到多個(gè)系統(tǒng)上去,這種分布的機(jī)制,是通過將Mysql的某一臺主機(jī)的數(shù)據(jù)復(fù)制到其它主機(jī)(slaves)上,并重新執(zhí)行一遍來實(shí)現(xiàn)的。
- 復(fù)制過程中一個(gè)服務(wù)器充當(dāng)主服務(wù)器,而一個(gè)或多個(gè)其它服務(wù)器充當(dāng)從服務(wù)器。主服務(wù)器將更新寫入二進(jìn)制日志文件,并維護(hù)文件的一個(gè)索引以跟蹤日志循環(huán)。
- 當(dāng)一個(gè)從服務(wù)器連接主服務(wù)器時(shí),它通知主服務(wù)器從服務(wù)器在日志中讀取的最后一次成功更新的位置。從服務(wù)器接收從那時(shí)起發(fā)生的任何更新,然后封鎖并等待主服務(wù)器通知新的更新。
需要注意的是:在進(jìn)行mysql復(fù)制時(shí),所有對復(fù)制中的表的更新必須在主服務(wù)器上進(jìn)行。否則必須要小心,以避免用戶對主服務(wù)器上的表進(jìn)行的更新與對從服務(wù)器上的表所進(jìn)行的更新之間的沖突。
Mysql支持 哪些復(fù)制
- 基于語句的復(fù)制: 在主服務(wù)器上執(zhí)行的SQL語句,在從服務(wù)器上執(zhí)行同樣的語句。MySQL默認(rèn)采用基于語句的復(fù)制,效率比較高。一旦發(fā)現(xiàn)沒法精確復(fù)制時(shí),會(huì)自動(dòng)選著基于行的復(fù)制。
- 基于行的復(fù)制:把改變的內(nèi)容復(fù)制過去,而不是把命令在從服務(wù)器上執(zhí)行一遍. 從mysql5.0開始支持
- 混合類型的復(fù)制: 默認(rèn)采用基于語句的復(fù)制,一旦發(fā)現(xiàn)基于語句的無法精確的復(fù)制時(shí),就會(huì)采用基于行的復(fù)制。
Mysql復(fù)制能解決的問題
- 數(shù)據(jù)分布 (Data distribution )
- 負(fù)載平衡(load balancing)
- 數(shù)據(jù)備份(Backups) ,保證數(shù)據(jù)安全
- 高可用性和容錯(cuò)行(High availability and failover)
- 實(shí)現(xiàn)讀寫分離,緩解數(shù)據(jù)庫壓力
主從復(fù)制原理
- master節(jié)點(diǎn)將數(shù)據(jù)的改變記錄二進(jìn)制binlog日志,當(dāng)master上的數(shù)據(jù)發(fā)生改變時(shí),則將其改變寫入二進(jìn)制binlog日志中;
- salve節(jié)點(diǎn)會(huì)在一定時(shí)間間隔內(nèi)對master二進(jìn)制binlog日志進(jìn)行探測其是否發(fā)生改變
- 如果發(fā)生改變,salve節(jié)點(diǎn)則開啟一個(gè)I/O線程請求讀取master二進(jìn)制binlog日志數(shù)據(jù)
- 同時(shí)master節(jié)點(diǎn)為每個(gè)slave請求啟動(dòng)一個(gè)dump線程,用于向slave發(fā)送日志數(shù)據(jù)
- slave節(jié)點(diǎn)接受并保存至本地的中繼日志relay log中
- slave節(jié)點(diǎn)將啟動(dòng)SQL寫庫線程從中繼日志中讀取二進(jìn)制日志數(shù)據(jù),在本地重放,使得其數(shù)據(jù)和主節(jié)點(diǎn)的保持一致
- 最后I/O線程和SQL線程將進(jìn)入睡眠狀態(tài),等待下一次被喚醒。
注意幾點(diǎn)
- master將操作語句記錄到binlog日志中,然后授予slave遠(yuǎn)程連接的權(quán)限(master一定要開啟binlog二進(jìn)制日志功能;通常為了數(shù)據(jù)安全考慮,slave也開啟binlog功能)。
- slave開啟兩個(gè)線程:IO線程和SQL線程。其中:IO線程負(fù)責(zé)讀取master的binlog內(nèi)容到中繼日志relay log里;SQL線程負(fù)責(zé)從relay log日志里讀出binlog內(nèi)容,并更新到slave的數(shù)據(jù)庫里,這樣就能保證slave數(shù)據(jù)和master數(shù)據(jù)保持一致了。
- Mysql復(fù)制至少需要兩個(gè)Mysql的服務(wù),當(dāng)然Mysql服務(wù)可以分布在不同的服務(wù)器上,也可以在一臺服務(wù)器上啟動(dòng)多個(gè)服務(wù)。
- Mysql復(fù)制最好確保master和slave服務(wù)器上的Mysql版本相同(如果不能滿足版本一致,那么要保證master主節(jié)點(diǎn)的版本低于slave從節(jié)點(diǎn)的版本)
- master和slave兩節(jié)點(diǎn)間時(shí)間需同步
流程圖如下:
如上圖所示:
- Mysql復(fù)制過程的第一部分就是master記錄二進(jìn)制日志。
在每個(gè)事務(wù)更新數(shù)據(jù)完成之前,master在二日志記錄這些改變。MySQL將事務(wù)串行的寫入二進(jìn)制日志,即使事務(wù)中的語句都是交叉執(zhí)行的。在事務(wù)寫入二進(jìn)制日志完成后,master通知存儲(chǔ)引擎提交事務(wù)。 - 第二部分就是slave將master的binary log拷貝到它自己的中繼日志。首先,slave開始一個(gè)工作線程——I/O線程。I/O線程在master上打開一個(gè)普通的連接,然后開始binlog dump process。Binlog dump process從master的二進(jìn)制日志中讀取事件,如果已經(jīng)跟上master,它會(huì)睡眠并等待master產(chǎn)生新的事件。I/O線程將這些事件寫入中繼日志。
- SQL slave thread(SQL從線程)處理該過程的最后一步。SQL線程從中繼日志讀取事件,并重放其中的事件而更新slave的數(shù)據(jù),使其與master中的數(shù)據(jù)一致。只要該線程與I/O線程保持一致,中繼日志通常會(huì)位于OS的緩存中,所以中繼日志的開銷很小。
- 此外,在master中也有一個(gè)工作線程:和其它MySQL的連接一樣,slave在master中打開一個(gè)連接也會(huì)使得master開始一個(gè)線程。
復(fù)制過程有一個(gè)很重要的限制——復(fù)制在slave上是串行化的,也就是說master上的并行更新操作不能在slave上并行操作。
Mysql復(fù)制的模式
- 主從復(fù)制:主庫授權(quán)從庫遠(yuǎn)程連接,讀取binlog日志并更新到本地?cái)?shù)據(jù)庫的過程;主庫寫數(shù)據(jù)后,從庫會(huì)自動(dòng)同步過來(從庫跟著主庫變);
- 主主復(fù)制:主從相互授權(quán)連接,讀取對方binlog日志并更新到本地?cái)?shù)據(jù)庫的過程;只要對方數(shù)據(jù)改變,自己就跟著改變;(如何解決沖突?)
Mysql主從復(fù)制的優(yōu)點(diǎn)
- 在從服務(wù)器可以執(zhí)行查詢工作(即我們常說的讀功能),降低主服務(wù)器壓力;(主庫寫,從庫讀,降壓)
- 在從主服務(wù)器進(jìn)行備份,避免備份期間影響主服務(wù)器服務(wù);(確保數(shù)據(jù)安全)
- 當(dāng)主服務(wù)器出現(xiàn)問題時(shí),可以切換到從服務(wù)器。(提升性能)
Mysql主從復(fù)制總結(jié)
-
主從復(fù)制條件
- 開啟Binlog功能
- 主庫要建立賬號
- 從庫要配置master.info(CHANGE MASTER to...相當(dāng)于配置密碼文件和Master的相關(guān)信息)
- start slave 開啟復(fù)制功能
需要了解的:
1)3個(gè)線程,主庫IO,從庫IO和SQL及作用
2)master.info(從庫)作用
3)relay-log 作用
4)異步復(fù)制
5)binlog作用(如果需要級聯(lián)需要開啟Binlog)需要注意:
1)主從復(fù)制是異步的邏輯的SQL語句級的復(fù)制
2)復(fù)制時(shí),主庫有一個(gè)I/O線程,從庫有兩個(gè)線程,I/O和SQL線程
3)實(shí)現(xiàn)主從復(fù)制的必要條件是主庫要開啟記錄binlog功能
4)作為復(fù)制的所有Mysql節(jié)點(diǎn)的server-id都不能相同
5)binlog文件只記錄對數(shù)據(jù)庫有更改的SQL語句(來自主庫內(nèi)容的變更),不記錄任何查詢(select,show)語句
Mysql主從環(huán)境部署一段時(shí)間后,發(fā)現(xiàn)主從不同步時(shí),如何進(jìn)行數(shù)據(jù)同步至一致?(請往下看)
主從同步中可能存在的問題
slave運(yùn)行過慢不能與master同步,也就是MySQL數(shù)據(jù)庫主從同步延遲
MySQL數(shù)據(jù)庫slave服務(wù)器延遲的現(xiàn)象是非常普遍的,這就導(dǎo)致了有了以下一些潛規(guī)則:“實(shí)時(shí)性要求不高的讀取操作可以放到slave服務(wù)器,實(shí)時(shí)性要求高的讀取操作放到master服務(wù)器”,“從機(jī)僅能做前一天的統(tǒng)計(jì)類查詢”。
slave同步延遲的原理
MySQL的主從復(fù)制都是單線程的操作,主庫對所有DDL和DML產(chǎn)生的日志寫進(jìn)binlog,由于binlog是順序?qū)懀孕屎芨摺?br> Slave的IO Thread線程從主庫中bin log中讀取取日志。
Slave的SQL Thread線程將主庫的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是隨即的,不是順序的,成本高很多。
由于SQL Thread也是單線程的,如果slave上的其他查詢產(chǎn)生lock爭用,又或者一個(gè)DML語句(大事務(wù)、大查詢)執(zhí)行了幾分鐘卡住了,那么所有之后的DML會(huì)等待這個(gè)DML執(zhí)行完才會(huì)繼續(xù)執(zhí)行,這就導(dǎo)致了延時(shí)。也許有人會(huì)質(zhì)疑:主庫上那個(gè)相同的DDL也會(huì)執(zhí)行幾分鐘,為什么slave會(huì)延時(shí)?原因是master可以并發(fā)執(zhí)行,而Slave_SQL_Running線程卻不可以。slave同步延遲的可能原因
1--slave的I/O線程推遲讀取日志中的事件信息;最常見原因是slave是在單線程中執(zhí)行所有事務(wù),而master有很多線程可以并行執(zhí)行事務(wù)。
2--帶來低效連接的長查詢、磁盤讀取的I/O限制、鎖競爭和innodb線程同步啟動(dòng)等。
3--Master負(fù)載;Slave負(fù)載
4--網(wǎng)絡(luò)延遲
5--機(jī)器配置(cpu、內(nèi)存、硬盤)
(主從同步延遲怎么產(chǎn)生的?)總之,當(dāng)主庫的TPS并發(fā)較高時(shí),產(chǎn)生的DDL數(shù)量超過slave一個(gè)sql線程所能處理的承受范圍時(shí),主從同步就會(huì)產(chǎn)生延時(shí);或者當(dāng)slave中有大型query語句產(chǎn)生了鎖等待也會(huì)產(chǎn)生延時(shí)。
-
如何查看同步延遲
1--可以通過比對master、slave上的日志位置
2--通過"show slave status"查看Seconds_Behind_Master的值,這個(gè)值代表主從同步延遲的時(shí)間,值越大說明延遲越嚴(yán)重。值為0為正常情況,正值表示已經(jīng)出現(xiàn)延遲,數(shù)字越大從庫落后主庫越多。
3--使用percona-toolkit的pt-hearbeat工具進(jìn)行查看。 -
減少同步延遲的操作方案
1--減少鎖競爭
如果查詢導(dǎo)致大量的表鎖定,需要考慮重構(gòu)查詢語句,盡量避免過多的鎖。
2--負(fù)載均衡
搭建多少slave,并且使用lvs或nginx進(jìn)行查詢負(fù)載均衡,可以減少每個(gè)slave執(zhí)行查詢的次數(shù)和時(shí)間,從而將更多的時(shí)間用于去處理主從同步。
3--salve較高的機(jī)器配置
4--Slave調(diào)整參數(shù)
為了保障較高的數(shù)據(jù)安全性,配置sync_binlog=1,innodb_flush_log_at_trx_commit=1等設(shè)置。而Slave可以關(guān)閉binlog,innodb_flush_log_at_trx_commit也可以設(shè)置為0來提高sql的執(zhí)行效率(這兩個(gè)參數(shù)很管用)
5--并行復(fù)制
即有單線程的復(fù)制改成多線程復(fù)制。
從庫有兩個(gè)線程與復(fù)制相關(guān):io_thread 負(fù)責(zé)從主庫拿binlog并寫到relaylog, sql_thread 負(fù)責(zé)讀relaylog并執(zhí)行。
多線程的思路就是把sql_thread 變成分發(fā)線程,然后由一組worker_thread來負(fù)責(zé)執(zhí)行。
幾乎所有的并行復(fù)制都是這個(gè)思路,有不同的,便是sql_thread 的分發(fā)策略。
MySQL5.7的真正并行復(fù)制enhanced multi-threaded slave(MTS)很好的解決了主從同步復(fù)制的延遲問題。
Mysql主從環(huán)境部署一段時(shí)間后,發(fā)現(xiàn)主從不同步時(shí),如何進(jìn)行數(shù)據(jù)同步至一致?
1 使用數(shù)據(jù)庫監(jiān)測監(jiān)測工具percona-toolkit
2 人工對比日志
Mysql最常用的三種備份工具:
- mysqldump:
通常為小數(shù)據(jù)情況下的備份
innodb: 熱備,溫備
MyISAM, Aria: 溫備
單線程備份恢復(fù)比較慢 - Xtrabackup(通常用innobackupex工具):
備份mysql大數(shù)據(jù)
InnoDB熱備,增量備份;
MyISAM溫備,不支持增量,只有完全備份
屬于物理備份,速度快; - lvm-snapshot:
接近于熱備的工具:因?yàn)橐日埱笕宙i,而后創(chuàng)建快照,并在創(chuàng)建快照完成后釋放全局鎖;
使用cp、tar等工具進(jìn)行物理備份;
備份和恢復(fù)速度較快;
很難實(shí)現(xiàn)增量備份,并且請求全局需要等待一段時(shí)間,在繁忙的服務(wù)器上尤其如此;