導(dǎo)致備庫延遲的原因舔痕。偶發(fā)性查詢、備份豹缀,備庫延遲影響分鐘級伯复,能追上來。
備庫執(zhí)行日志的速度持續(xù)低于主庫生成日志的速度邢笙,延遲小時(shí)級別啸如。壓力持續(xù)高主庫來說,永遠(yuǎn)都追不上
1氮惯、備庫并行復(fù)制能力
黑色的兩個(gè)箭頭:寫入主庫(并行度高)叮雳,備庫上 sql_thread 執(zhí)行中轉(zhuǎn)日志(relay log)。
????主庫:妇汗,各種鎖影響并發(fā)度帘不。支持行鎖,除極端場杨箭,并發(fā)度好寞焙。并發(fā)壓測線程 32 就比單線程時(shí),總吞吐量高。
????備庫: sql_thread 更新數(shù)據(jù) (DATA) 的邏輯捣郊。單線程主備延遲(5.6 之前)辽狈,主庫并發(fā)高、TPS 高嚴(yán)重主備延遲
2模她、復(fù)制機(jī)制:sql_thread拆成多個(gè)線程
coordinator 就是sql_thread, 不直接更新稻艰,只讀中轉(zhuǎn)日志和分發(fā)事務(wù)。真正更新日志worker 線程侈净。個(gè)數(shù)slave_parallel_workers 8~16 之間最好(32 核物理機(jī))尊勿,備庫提供讀查詢,不能把 CPU 都吃光畜侦。
3元扔、coordinator 分發(fā)兩個(gè)基本要求:
????1)不能更新覆蓋。更新同一行兩個(gè)事務(wù)旋膳,分發(fā)同一worker 中澎语。
????例:第二個(gè)比第一個(gè)事務(wù)先執(zhí)行。主验懊、備執(zhí)行順序相反擅羞,不一致
????2)?同一事務(wù)放同一個(gè) worker 中。
例:事務(wù)更新了表 t1 义图、2 各一行减俏,分到不同 worker ,最終結(jié)果主備一致的碱工, t1 執(zhí)行完成瞬間娃承,備庫上有一個(gè)查詢,看到事務(wù)“更新了一半的結(jié)果”怕篷,破壞隔離性历筝。
一、MySQL 5.5 并行復(fù)制策略
不支持并行復(fù)制的廊谓。備庫單線程復(fù)制梳猪。
1.1按表分發(fā)策略
兩個(gè)事務(wù)更新不同表,可并行蒸痹。如是跨表事務(wù)春弥,放一起考慮。
每個(gè) worker 線程對應(yīng)一個(gè) hash 表电抚,保存當(dāng)前正在這個(gè) worker “執(zhí)行隊(duì)列”事務(wù)所涉及的表。hash 表 key 是“庫名. 表名”竖共,value 數(shù)字蝙叛,隊(duì)列多少個(gè)事務(wù)修改表。
有事務(wù)分配給 worker 時(shí)公给,事務(wù)里面涉及的表會(huì)被加到對應(yīng)的 hash 表中借帘。worker 執(zhí)行完成后蜘渣,這個(gè)表會(huì)被從 hash 表中去掉。
圖 3 中肺然,hash_table_1 表示蔫缸,現(xiàn)在 worker_1 的“待執(zhí)行事務(wù)隊(duì)列”里,有 4 個(gè)事務(wù)涉及到 db1.t1 表际起,有1 涉及到 db2.t2 表拾碌;hash_table_2 worker_2 有一個(gè)事務(wù)會(huì)更新到表 t3 的數(shù)據(jù)。
coordinator 從中轉(zhuǎn)日志中讀入一個(gè)新事務(wù) T街望,這個(gè)事務(wù)修改的行涉及到表 t1 和 t3校翔。
事務(wù) T 的分配流程,看分配規(guī)則灾前。
1. 由于事務(wù) T 中涉及修改表 t1防症,worker_1 隊(duì)列中有事務(wù)在修改表 t1,事務(wù) T 和隊(duì)列中的某個(gè)事務(wù)要修改同一個(gè)表的數(shù)據(jù)哎甲,沖突蔫敲。
2. 順序判斷事務(wù) T 和每個(gè) worker 隊(duì)列的沖突關(guān)系,事務(wù) T 跟 worker_2 也沖突炭玫。
3. T 跟多于一個(gè) worker 沖突奈嘿,coordinator 等待。
4.? 每個(gè) worker 繼續(xù)執(zhí)行础嫡,同時(shí)修改 hash_table指么。假設(shè) hash_table_2里面涉及到修改表 t3 的事務(wù)先執(zhí)行完成,從 hash_table_2中把 db1.t3 這一項(xiàng)去掉榴鼎。
5.? 沖突的 worker 只有 worker_1 了伯诬,因此就把它分配給 worker_1。
6.? coordinator 讀下一個(gè)中轉(zhuǎn)日志巫财,分配事務(wù)盗似。
worker 沖突關(guān)系包括以下三種情況:
1.? 跟所有 worker 都不沖突,coordinator 分配給最空閑woker;
2.? 跟多于一個(gè) worker 沖突平项,coordinator 等待狀態(tài)赫舒,直到只剩1 個(gè);
3.? 只跟一個(gè) worker 沖突闽瓢,分配給這個(gè) worker接癌。
負(fù)載均勻效果好。熱點(diǎn)表扣讼,涉及某一個(gè)表的時(shí)候缺猛,所有事務(wù)都會(huì)被分配到同一個(gè) worker 中,單線程復(fù)制。
1.2按行分發(fā)策略
沒更新相同行荔燎,備庫可并行耻姥。 binlog 格式 row。
這時(shí)候有咨,我們判斷一個(gè)事務(wù) T 和 worker 是否沖突琐簇,用的就規(guī)則就不是“修改同一個(gè)表”,而是“修改同一行”座享。
數(shù)據(jù)結(jié)構(gòu)差不多婉商,為每個(gè) worker, hash 表征讲。key据某,“庫名 + 表名 + 唯一鍵值”。
唯一鍵:除了主鍵诗箍,還有唯一索引 a:主庫執(zhí)行這兩個(gè)事務(wù):
更新的行主鍵值不同癣籽,分到不同的 worker,B 先執(zhí)行滤祖。 id=1 行 a 值還是 1筷狼,唯一鍵沖突。
因此匠童,基于行的策略埂材,事務(wù) hash 表中還需要考慮唯一鍵, key “庫名 + 表名 + 索引 a 的名字 +a 的值”汤求。
表 t1 上執(zhí)行 update t1 set a=1 where id=2 語句俏险, binlog 記錄行修改前后各個(gè)字段值。
coordinator在解析這個(gè)語句的 binlog 時(shí)扬绪,hash 表三個(gè)項(xiàng):
1. key=hash_func(db1+t1+“PRIMARY”+2), value=2; 修改前后行 id 值不變竖独,出現(xiàn)兩次
2.? key=hash_func(db1+t1+“a”+2), value=1,影響表 a=2 行
3.? key=hash_func(db1+t1+“a”+1), value=1挤牛,影響表 a=1 行
按行并行莹痢,消耗更多計(jì)算資源。約束條件:
1.? 從 binlog 里解析出表名墓赴、主鍵值和唯一索引的值竞膳。主庫 binlog 格式必須row;
2.? 必須有主鍵诫硕;
3.? 不能有外鍵坦辟。級聯(lián)更新行不記錄 binlog 中,沖突檢測不準(zhǔn)確章办。
按行并行度高锉走。大事務(wù)的話滔吠,兩個(gè)問題:
1. 耗內(nèi)存。刪除 100 萬行挠日, hash 表記錄 100 萬項(xiàng)。
2. 耗CPU翰舌。解析 binlog嚣潜,計(jì)算 hash 值,成本高椅贱。
設(shè)置一個(gè)閾值懂算,單個(gè)事務(wù)如果超過設(shè)置的行數(shù)閾值(比如,如果單個(gè)事務(wù)更新的行數(shù)超過 10 萬行)庇麦,退化為單線程模式:
1.? coordinator 暫時(shí) hold 住事務(wù)计技;
2.? 所有 worker 執(zhí)行完,成空隊(duì)列山橄;
3.? coordinator 直接執(zhí)行這個(gè)事務(wù)垮媒; 恢復(fù)并行模式。
二航棱、MySQL 5.6 版本并行復(fù)制策略
并行復(fù)制睡雇,按庫并行。理解了上面介紹的按表分發(fā)策略和按行分發(fā)策略饮醇,你就理解了它抱,用于決定分發(fā)策略的 hash 表里,key 就是數(shù)據(jù)庫名朴艰。
取決于壓力模型观蓄。多個(gè) DB壓力均衡,效果好祠墅。
優(yōu)勢:
1. 構(gòu)造 hash 值快侮穿,只要庫名;實(shí)例上 DB 數(shù)不多饵隙,不會(huì)出現(xiàn)需要構(gòu)造 100 萬個(gè)項(xiàng)這種情況撮珠。
2.? 不要求 binlog 格式。statement 格式binlog 很容易拿到庫名金矛。
沒效果:主庫上的表都放在同一個(gè) DB 里面芯急,;不同 DB 熱點(diǎn)不同驶俊,一個(gè)是業(yè)務(wù)邏輯庫压真,一個(gè)是系統(tǒng)配置庫
創(chuàng)建不同的 DB热幔,把相同熱度的表均勻分到這些不同的 DB 中,強(qiáng)行用。由于需要特地移動(dòng)數(shù)據(jù),用得并不多豺撑。
三、MariaDB 的并行復(fù)制策略
在第 23 篇文章中, redo log 組提交 (group commit) 優(yōu)化紊婉, MariaDB 并行復(fù)制就是這個(gè)特性:
1.? 同一組里提交的事務(wù),不修改同一行辑舷;
2.? 主庫上并行喻犁,備庫也可。
MariaDB 是這么做的:
1.? 組里一起提交事務(wù)何缓,相同commit_id
2.? commit_id 直接寫binlog 里肢础;
3.? 傳備庫時(shí),相同 commit_id 分發(fā)多個(gè) worker 執(zhí)行碌廓;
4.? 執(zhí)行完传轰,coordinator 取下一批,commit_id+1谷婆。
之前都是“分析 binlog慨蛙,拆分到 worker”上。MariaDB “模擬主庫并行模式”纪挎。
問題:備庫沒真正并行股淡。主庫trx1、trx2 和 trx3 提交時(shí)廷区,trx4唯灵、trx5 和 trx6 在執(zhí)行的。提交完隙轻,下一組很快 commit
MariaDB 并行復(fù)制策略埠帕,備庫上執(zhí)行如圖 6
備庫上玖绿,第一組完成敛瓷,第二組才開始,吞吐量不夠斑匪。
容易被大事務(wù)拖后腿呐籽。trx2超大事務(wù),備庫trx1 和 trx3 執(zhí)行完成后蚀瘸,只能等 trx2完成狡蝶,只有worker 工作,浪費(fèi)贮勃。
四贪惹、MySQL 5.7 的并行復(fù)制策略
類似功能,參數(shù)slave-parallel-type 控制并行復(fù)制策略:
1.? ?DATABASE寂嘉, 5.6 并行策略奏瞬;
2.? ?LOGICAL_CLOCK枫绅,MariaDB 。做優(yōu)化
“執(zhí)行狀態(tài)”所有事務(wù)硼端,不能同時(shí)并行并淋,鎖沖突而等待,備庫分配不同worker珍昨,不一致预伺。
redo log prepare、?commit 狀態(tài)曼尊,表示已通過鎖沖突。并行思想:
1. 同時(shí)prepare 狀態(tài)脏嚷,備庫可并行骆撇;
2.? prepare 、 commit 之間父叙,備庫也可并行神郊。
?binlog 組提交兩個(gè)參數(shù),主庫提交慢趾唱,讓備庫快涌乳。提升備庫復(fù)制并發(fā)度:
1.? binlog_group_commit_sync_delay 延遲多少微秒后才調(diào)用fsync;
2.? binlog_group_commit_sync_no_delay_count 累積多少次調(diào)用 fsync。
五甜癞、MySQL 5.7.22 并行復(fù)制策略
基于WRITESET 并行復(fù)制夕晓。增加binlog-transaction-dependency-tracking控制是否啟用新策略。參數(shù)三種:
1.? COMMIT_ORDER悠咱,同時(shí)進(jìn)入 prepare 和 commit 判斷可否并行
2.? WRITESET蒸辆,更新每行,計(jì)算 hash 值析既,組成集合 writeset躬贡。兩個(gè)事務(wù)沒有操作相同的行,writeset 沒交集眼坏,可并行拂玻。
3.? WRITESET_SESSION,WRITESET 多了約束宰译,主庫先后執(zhí)行兩事務(wù)檐蚜,備庫相同順序。
唯一標(biāo)識(shí) hash 值:“庫名 + 表名 + 索引名 + 值”沿侈。還有其他唯一索引熬甚,每個(gè)唯一索引,insert 對應(yīng) writeset 多增加 hash 值肋坚。
優(yōu)勢:
1.? writeset 主庫生成后寫入binlog 面乡括,備庫不需解析 binlog(event 里的行數(shù)據(jù))肃廓,省計(jì)算量;
2.? 不需掃一遍binlog 決定分發(fā)到哪個(gè) worker诲泌,省內(nèi)存盲赊;
3.? 備庫分發(fā)策略不依賴binlog ,statement 也可
通用有保證敷扫。“表上沒主鍵”和“外鍵約束”場景哀蘑,WRITESET 策略沒法并行,暫時(shí)退化為單線程
小結(jié)
MySQL各種多線程復(fù)制策略葵第。不同策略優(yōu)缺點(diǎn)
為什么要有多線程復(fù)制呢绘迁?單線程復(fù)制能力低,更新壓力大主庫卒密,備庫追不上主庫∽禾ǎ現(xiàn)象:備庫seconds_behind_master 值越來越大
大事務(wù)不僅會(huì)影響主庫,備庫復(fù)制延遲哮奇。建議大事務(wù)拆小
MySQL5.7 備庫并行策略膛腐,修改binlog,并不是向上兼容的鼎俘,在主備切換哲身、版本升級的時(shí)候需要把這個(gè)因素也考慮進(jìn)去。
思考題
MySQL 5.7.22版本主庫贸伐,單線程插入很多勘天,3 小時(shí)后,給主庫搭相同備庫
更快追上主庫捉邢,并行復(fù)制误辑。binlog-transaction-dependency-tracking 參數(shù) COMMIT_ORDER、WRITESET 和WRITE_SESSION 選擇哪個(gè)歌逢?原因是巾钉?另外兩個(gè)現(xiàn)象?
WRITESET秘案。其他兩個(gè)單線程砰苍。
評論1
同行更新幾個(gè)事務(wù), commit_id 相同阱高,備庫并行執(zhí)行不一致赚导?
同一行事務(wù)不可能同時(shí)commit。