一、異步復(fù)制
異步復(fù)制原理圖
- master:
- Dump_Thread垒拢,通知IO_Thread數(shù)據(jù)變更
- slave:
- IO_Thread旬迹,拉取binlog增量
- SQL_Thread,SQL邏輯重放
異步復(fù)制流程
- master 寫undo求类、redo
- master 發(fā)起commit奔垦,寫binlog(filename,position)
- master 完成提交事務(wù)
- slave 通過(guò)IO_Thread拉取binlog的filename尸疆,position椿猎,并寫入到本地的relaylog中
- slave 通過(guò)SQL_Thread邏輯重放relaylog中的SQL(單線程)
兩種場(chǎng)景
- 實(shí)時(shí)同步(IO_Thread主從沒(méi)有延遲),寫數(shù)據(jù)之前通知IO_Thread有變更寿弱,IO_Thread拉取binlog增量
- 主從長(zhǎng)時(shí)間延遲(全備恢復(fù))犯眠,IO_Thread直接去主庫(kù)本地磁盤拉取binlog增量
復(fù)制中的坑
-
row模式下,表最好是有主鍵症革,其次要有普通索引筐咧。否則sql_thread重放需要全表掃描匹配,速度非常慢(mysql5.7中做了優(yōu)化)
二噪矛、半同步復(fù)制(MySQL 5.5 after commit)
半同步復(fù)制流程圖
半同步復(fù)制流程
- master 寫undo嗜浮、redo
- master 發(fā)起commit,sync binlog(filename摩疑,position)
- master 存儲(chǔ)引擎commit完成
- master_sender_thread 等待slave_reciver_thread返回ack(等待過(guò)程中會(huì)阻塞下一個(gè)事務(wù))
- master_sender_thread接收到slave_reciver_thread返回的ack,并返回給客戶端畏铆,客戶端才可以繼續(xù)操作
after帶來(lái)的三個(gè)問(wèn)題
- 性能問(wèn)題:AFTER_COMMIT半同步是單線程處理的雷袋,master把事務(wù)發(fā)送完畢后,要接受和處理slave的ack應(yīng)答辞居,處理完ack后才能繼續(xù)發(fā)送下一個(gè)事務(wù)楷怒,對(duì)性能影響比較大
- master commit完成后才開始等待slave的ACK,其實(shí)這個(gè)時(shí)候在master上事務(wù)已經(jīng)提交完成并且其他客戶端已經(jīng)可以讀到瓦灶,只是提交該事物的客戶端處于等待狀態(tài)鸠删。
- 如果master等待ack時(shí)master crash,而slave又未接收到該事務(wù)的話贼陶,那么切換到從庫(kù)后就會(huì)出現(xiàn)讀取的結(jié)果不一致的情況(因?yàn)橹鲙?kù)已commit而從庫(kù)未收到該事務(wù)binlog)
三刃泡、增強(qiáng)半同步復(fù)制(MySQL 5.7 after sync)
增強(qiáng)半同步復(fù)制流程圖
增強(qiáng)半同步復(fù)制流程
- master 寫undo巧娱、redo
- master 發(fā)起commit,sync binlog(filename烘贴,position)
- master 通過(guò)單獨(dú)的semisync_reciver_thread等待slave_reciver_thread返回ack禁添,此過(guò)程中master_sender_thread可以處理其他事務(wù)的請(qǐng)求
- semisync_reciver_thread接收到slave_reciver_thread返回的ack,并返回給客戶端
- master 存儲(chǔ)引擎層commit
增強(qiáng)半同步解決的問(wèn)題
- AFTER_SYNC采用雙工處理桨踪,master采用單獨(dú)semisync_reciver_thread處理ack應(yīng)答老翘,不阻塞其他事務(wù),提升性能
- AFTER_SYNC等待ack的操作是在引擎層commit之前處理锻离,避免了其他客戶端臟讀
- 在等待ack的期間master crash铺峭,由于master引擎層未commit,如果slave未接受到該事務(wù)汽纠,那么數(shù)據(jù)是一致的
增強(qiáng)半同步帶來(lái)的新問(wèn)題
極端情況:在master sync binlog(寫入xid)后卫键,且在發(fā)送日志之前,這個(gè)時(shí)間master crash了疏虫。那么slave是沒(méi)有拿到master的binlog增量的永罚,而master重啟后的crash recovery會(huì)認(rèn)為該事務(wù)已寫到binlog中,然后進(jìn)行重做卧秘。這樣就會(huì)導(dǎo)致主從不一致
5.7增強(qiáng)半同步配置
- master
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
set global rpl_semi_sync_master_enabled=ON;
- slave
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
set global rpl_semi_sync_slave_enabled=ON;
- 主要參數(shù)
- mster:
- rpl_semi_sync_master_enabled=ON 表示在master上已經(jīng)開啟半同步復(fù)制模式呢袱。
- rpl_semi_sync_master_timeout=10000 該參數(shù)默認(rèn)為10000毫秒,即10秒翅敌,可以調(diào)整羞福,表示如果主庫(kù)在某次事務(wù)中等待事件超過(guò)10秒,則降級(jí)為異步復(fù)制模式蚯涮,不再等待slave治专,如果master探測(cè)到slave恢復(fù),則會(huì)自動(dòng)回到半同步模式遭顶。
- rpl_semi_sync_master_wait_no_slave=ON 表示是否允許master每個(gè)事務(wù)提交后都要等待slave的確認(rèn)信號(hào)张峰,默認(rèn)是ON,即每一個(gè)事務(wù)都會(huì)等待棒旗,如果是OFF喘批,則slave追趕上之后,也不會(huì)回到半同步模式铣揉。
- rpl_semi_sync_master_trace_level=32 表示開啟半同步復(fù)制模式時(shí)的調(diào)試級(jí)別饶深,默認(rèn)是32
- slave:
- rpl_semi_sync_slave_enabled=ON
- rpl_semi_sync_master_trace_level=32
四、并行復(fù)制
并行復(fù)制的演變
- MySQL 5.6 是基于庫(kù)級(jí)別的并行復(fù)制(適用于單實(shí)例多庫(kù)而且?guī)熘g的寫入分布比較平均的情況逛拱,比較雞肋敌厘,可以忽略)
- MySQL 5.7 是基于事務(wù)級(jí)別的并行復(fù)制(主要介紹)
- MySQL 8.0 是基于行級(jí)別的并行復(fù)制(太新還沒(méi)來(lái)得及研究,后面補(bǔ)上)
MySQL 5.7基于行的并行復(fù)制
原理:
與組提交結(jié)合朽合,一個(gè)組提交的事務(wù)都是可以并行回放俱两,因?yàn)檫@些事務(wù)都已進(jìn)入到事務(wù)的prepare階段饱狂,則說(shuō)明事務(wù)之間沒(méi)有任何沖突(否則就不可能提交)。
復(fù)制中的重要參數(shù)
- log-bin = /binlog_dir
- binlog_format = row
- binlog_row_image = full //默認(rèn)full
- gtid_mode = on
- enforce_gtid_consistency = on //打開gtid之前必須打開此選項(xiàng)锋华,服務(wù)器通過(guò)允許僅執(zhí)行可使用GTID安全記錄的語(yǔ)句來(lái)強(qiáng)制執(zhí)行GTID一致性(開啟后強(qiáng)制檢測(cè)gtid一致性嗡官,在事務(wù)中更改非事務(wù)表將會(huì)報(bào)錯(cuò))
- binlog_group_commit_sync_delay = 100 //單位(微秒)。如果不啟用組提交毯焕,則每次提交一個(gè)事務(wù)衍腥,binlog做一次fsync。如果啟用了binlog-group-commit纳猫,此時(shí)sync_binlog=N代表每N組事務(wù)婆咸,而不是每N個(gè)事務(wù)。建議設(shè)置sync_binlog=1
- binlog_group_commit_sync_no_delay_count = 10
- binlog_order_commit = off //開啟后事務(wù)提交順序與binlog順序一致芜辕,默認(rèn)on尚骄,設(shè)置為off則事務(wù)可并行提交,對(duì)數(shù)據(jù)一致性可能產(chǎn)生影響侵续。如果啟用了binlog-group-commit倔丈,則設(shè)置為off
- transaction_write_set_extraction = on //8.0特性,5.7默認(rèn)off
- binlog_transation_dependency_tracking = COMMIT_ORDER //等同于打開binlog_order_commit状蜗,基于行級(jí)別并行復(fù)制配置成writeset_session
- binlog_transation_dependency_history_size = 25000 //控制隊(duì)列長(zhǎng)度
- slave_net_timeout = 20|30 //io_thread超時(shí)時(shí)間
- log_slave_updates
- slave_parallel_type = LOGICAL_CLOCK //從庫(kù)開啟并行復(fù)制
- slave_parallel_type = 4|8
- slave_preserve_commit_order = on //保證從庫(kù)提交順序與主庫(kù)一致需五,前置條件log-bin,log_slave_update轧坎,slave_parallel_type = LOGICAL_CLOCK
- slave_rows_search_algorithms = TABLE_SCAN,INDEX_SCAN //配置成INDEX_SCAN,HASH_SCAN宏邮,當(dāng)沒(méi)主鍵的表復(fù)制中可以用hash索引
- relay_log_info_reposity = table //crash-safe replication
- sync_relay_log_info = 1
- relay_log_recovery = 1