定性、查詢服務(wù)競(jìng)態(tài)修復(fù)與半同步一致性治理)
Vitess v15.0.5 變更深度解析Online DDL 穩(wěn)定性、查詢服務(wù)競(jìng)態(tài)修復(fù)與半同步一致性治理【免費(fèi)下載鏈接】vitessVitess is a database clustering system for horizontal scaling of MySQL.項(xiàng)目地址: https://gitcode.com/gh_mirrors/vi/vitess本篇技術(shù)指南圍繞 Vitess v15.0.5release-15.0 分支補(bǔ)丁版本的官方變更記錄展開逐項(xiàng)解析本次版本在 Online DDL、Query Serving、TabletManager 半同步復(fù)制、集群備份管理以及 CI/構(gòu)建工程化上的修復(fù)動(dòng)機(jī)、實(shí)現(xiàn)原理與升級(jí)影響并結(jié)合當(dāng)前倉(cāng)庫(kù)源碼驗(yàn)證每一條修復(fù)背后的真實(shí)調(diào)用鏈幫助讀者在升級(jí) v15 分支前準(zhǔn)確評(píng)估風(fēng)險(xiǎn)收益、理解各修復(fù)在代碼層面的落點(diǎn)。版本定位v15 生命周期內(nèi)的第五個(gè)補(bǔ)丁版本v15.0.5是 Vitess 15.0 穩(wěn)定分支release-15.0的第五個(gè)補(bǔ)丁版本。從變更記錄changelog/15.0/15.0.5/changelog.md看本次發(fā)布以穩(wěn)定性修復(fù)為絕對(duì)主線共覆蓋五大類別Bug fixes包含 Build/CI、Cluster management、Online DDL、Query Serving、TabletManager 五個(gè)子類CI/Build文檔生成工具鏈docgen與 vtorc 容器化改進(jìn)Documentation自動(dòng)生成文檔的路徑匿名化Internal Cleanup升級(jí)測(cè)試 Go 版本Releasev15.0.5 代碼凍結(jié)TestingCI 環(huán)境下的 reparent 測(cè)試清理與 FOSSA 測(cè)試移除。其中 Online DDL 相關(guān)修復(fù)占據(jù)了近一半的變更量是本版本當(dāng)之無(wú)愧的核心主題緊隨其后的是查詢服務(wù)Query Serving的多個(gè)競(jìng)態(tài)條件修復(fù)。下文按類別逐一展開。Online DDL本版本的重頭戲v15.0.5 共包含 5 項(xiàng) Online DDL 相關(guān)修復(fù)覆蓋并發(fā)安全、策略語(yǔ)義、狀態(tài)機(jī)一致性、產(chǎn)物清理四個(gè)維度。RevertMigration.Comment 讀寫并發(fā)問(wèn)題變更記錄指出本版本解決了RevertMigration.Comment的讀寫并發(fā)問(wèn)題PR #13735。Revert 操作在 Vitess 中用于回滾一條已執(zhí)行的 Online DDL 遷移當(dāng)REVERT語(yǔ)句提交后vttablet 會(huì)解析被回滾遷移的元數(shù)據(jù)生成一條新的遷移記錄并建立reverted_uuid關(guān)聯(lián)。從 executor.go 的SubmitMigration實(shí)現(xiàn)可以看到L5470 附近提交 REVERT 遷移時(shí)會(huì)通過(guò)onlineDDL.GetRevertUUID()解析出被回滾遷移的 UUID并將其作為reverted_uuid寫入_vt.schema_migrations表。Comment字段的并發(fā)讀寫如果不加保護(hù)在多協(xié)程同時(shí)讀取/回填遷移注釋時(shí)可能產(chǎn)生數(shù)據(jù)競(jìng)態(tài)導(dǎo)致注釋內(nèi)容錯(cuò)亂甚至 panic。該修復(fù)即針對(duì)這一數(shù)據(jù)結(jié)構(gòu)的并發(fā)訪問(wèn)路徑加鎖或改用原子語(yǔ)義確保 Revert 場(chǎng)景下遷移注釋的一致可讀。immediate operations 語(yǔ)義正式化與 --postpone-completionPR #13832 是本次 Online DDL 修復(fù)中語(yǔ)義影響最大的一項(xiàng)正式化 immediate operations即時(shí)操作概念并讓 DDL strategy 標(biāo)志--postpone-completion對(duì)這類操作生效。所謂 immediate operations指那些不依賴數(shù)據(jù)拷貝copy階段、可以立刻完成的 DDL 操作例如CREATE TABLE、DROP TABLE以及 MySQL 8.0 支持INSTANT算法的部分列操作。在 executor.go 中可以找到該語(yǔ)義在代碼中的完整落點(diǎn)L2179從遷移記錄中讀取is_immediate_operation布爾字段L2188-2190注釋明確說(shuō)明即時(shí)操作天生具備 ready to complete 狀態(tài)inherently ready to complete因?yàn)槠洳僮鞅旧砭褪羌磿r(shí)的L2197判斷!isImmediateOperation || !postponeCompletion決定遷移是否可以立即進(jìn)入完成流程L2262-2301reviewImmediateOperations注釋定義了何謂即時(shí)操作、何謂非即時(shí)操作例如針對(duì)真實(shí)ALTER TABLE的 REVERT 就不屬于即時(shí)操作L3331、L3364-3366在in-order completion按序完成模式下即時(shí)操作必須位于其遷移上下文中第一個(gè)待處理位置因?yàn)樗谶\(yùn)行后一至兩秒內(nèi)即可完成。對(duì)用戶而言這意味著此前--postpone-completion標(biāo)志對(duì)某些本應(yīng)立即完成的遷移失效的問(wèn)題得到解決。策略標(biāo)志現(xiàn)在能夠統(tǒng)一控制何時(shí)讓遷移真正完成cut-over而無(wú)論其底層是即時(shí)操作還是需要數(shù)據(jù)拷貝的重型操作。需要特別指出的是--postpone-completion并非所有策略都支持從 executor.go L2341-2342 可以看到當(dāng) DDL 策略為mysql即直接透?jìng)?MySQL 原生 DDL時(shí)會(huì)直接返回INVALID_ARGUMENT錯(cuò)誤提示--postpone-completion not supported in mysql strategy。修復(fù)取消遷移的 completed_timestamp 為空PR #13935 修復(fù)了被取消cancelled的遷移completed_timestamp為 NULL 的問(wèn)題。該字段在 Online DDL 狀態(tài)機(jī)中承擔(dān)遷移何時(shí)結(jié)束的語(yǔ)義而清理邏輯artifact cleanup依賴它計(jì)算產(chǎn)物保留時(shí)長(zhǎng)。對(duì)應(yīng)的修復(fù)在 schema.go 中新增了sqlFixCompletedTimestamp語(yǔ)句L428-435UPDATE _vt.schema_migrations SET completed_timestampNOW(6) WHERE migration_status IN (cancelled, failed) AND cleanup_timestamp IS NULL AND completed_timestamp IS NULL即對(duì)于處于cancelled或failed狀態(tài)、尚未清理且完成時(shí)間缺失的遷移回填當(dāng)前時(shí)間戳。這一補(bǔ)賬操作保證了清理調(diào)度器見(jiàn)下文在計(jì)算completed_timestamp NOW() - INTERVAL retain_artifacts_seconds時(shí)不會(huì)因?yàn)?NULL 時(shí)間戳而跳過(guò)或誤判歷史遷移從而避免取消/失敗遷移的產(chǎn)物永遠(yuǎn)得不到回收。取消遷移產(chǎn)物清理與 --retain-artifacts 策略標(biāo)志PR #14035 是另一項(xiàng)重量級(jí)修復(fù)清理被取消遷移的殘留產(chǎn)物并支持--retain-artifactsdurationDDL 策略標(biāo)志。在 v15.0.5 之前遷移一旦被取消其創(chuàng)建的表如_vt_xxx_gho影子表、_vt_xxx_ghc變更日志表、_vt_xxx_del延遲刪除表等 artifacts可能因清理?xiàng)l件不滿足而長(zhǎng)期滯留。修復(fù)后清理邏輯統(tǒng)一由sqlSelectUncollectedArtifacts驅(qū)動(dòng)schema.go L414-427SELECT migration_uuid, artifacts, log_path FROM _vt.schema_migrations WHERE migration_status IN (complete, cancelled, failed) AND cleanup_timestamp IS NULL AND completed_timestamp IF(retain_artifacts_seconds0, NOW() - INTERVAL %a SECOND, NOW() - INTERVAL retain_artifacts_seconds SECOND ) ORDER BY id可見(jiàn)清理?xiàng)l件同時(shí)覆蓋complete、cancelled、failed三種終態(tài)且每個(gè)遷移的保留時(shí)長(zhǎng)可獨(dú)立控制retain_artifacts_seconds0時(shí)回退到全局默認(rèn)保留時(shí)長(zhǎng)%a占位符否則按遷移自身的保留時(shí)長(zhǎng)計(jì)算。--retain-artifacts策略標(biāo)志的生效邏輯位于 executor.go L5471-5475retainArtifactsSeconds : int64(retainOnlineDDLTables.Seconds()) if retainArtifacts, _ : onlineDDL.StrategySetting().RetainArtifactsDuration(); retainArtifacts ! 0 { // Explicit retention indicated by --retain-artifact DDL strategy flag for this migration. Override! retainArtifactsSeconds int64(retainArtifacts.Seconds()) }即遷移級(jí)策略標(biāo)志優(yōu)先于 vttablet 全局的retainOnlineDDLTables配置最終隨sqlInsertMigration一并寫入_vt.schema_migrations.retain_artifacts_seconds字段L5498。典型用法ALTER TABLE my_table DROP COLUMN c1, ALGORITHMghost, --retain-artifacts168h;這允許運(yùn)維針對(duì)個(gè)別大表顯式延長(zhǎng)或縮短影子表保留期例如調(diào)試期間想多留幾天影子表做比對(duì)而無(wú)需改動(dòng)全局參數(shù)。修復(fù)改列名與列類型為 JSON 的 bugPR #14115 修復(fù)了將列名與列類型同時(shí)改為 JSON時(shí)的錯(cuò)誤。這類 DDL 形如ALTER TABLE t CHANGE COLUMN old_col new_col JSON在 Online DDL 的 ghost/切表流程中涉及列映射column list推導(dǎo)與 vreplication 字段映射邊界場(chǎng)景處理不當(dāng)會(huì)導(dǎo)致遷移失敗或數(shù)據(jù)錯(cuò)位。該修復(fù)屬于 Online DDL 邊界條件正確性的收尾工作。Query Serving四處競(jìng)態(tài)與代價(jià)模型修正schema tracker 遍歷表/視圖時(shí)的競(jìng)態(tài)PR #13794 修復(fù)了 vttablet 端 schema tracker 在**遍歷表tables與視圖views**時(shí)存在的競(jìng)態(tài)條件。schema tracker 維護(hù)內(nèi)存中的 schema 緩存供 vtgate 下發(fā)查詢計(jì)劃時(shí)引用。當(dāng)后臺(tái) refresh 線程在更新 schema 的同時(shí)查詢線程正在迭代表/視圖列表若無(wú)鎖保護(hù)會(huì)觸發(fā) data race進(jìn)而可能導(dǎo)致計(jì)劃構(gòu)建讀到半更新?tīng)顟B(tài)的 schema。該修復(fù)在迭代路徑上補(bǔ)齊了同步保護(hù)屬于典型的并發(fā)訪問(wèn)正確性問(wèn)題。模糊測(cè)試fuzzing發(fā)現(xiàn)的一批 bug 修復(fù)PR #13807 匯總了 vitess 團(tuán)隊(duì)在持續(xù)模糊測(cè)試中發(fā)現(xiàn)的若干問(wèn)題。Vitess 倉(cāng)庫(kù)中維護(hù)了專門的 fuzzer可參見(jiàn) go/mysql/mysql_fuzzer.goSQL 解析器、協(xié)議解析路徑是重點(diǎn)目標(biāo)。這類修復(fù)通常涉及畸形 SQL 導(dǎo)致解析器 panic極端輸入導(dǎo)致內(nèi)存分配失控錯(cuò)誤處理路徑中再次拋出異常掩蓋原始錯(cuò)誤。建議升級(jí)用戶在發(fā)布說(shuō)明之外重點(diǎn)關(guān)注 SQL 兼容性邊界因?yàn)槟:郎y(cè)試修復(fù)往往悄悄改變了某些邊緣語(yǔ)法的處理行為。join 引擎 OLAP 流式執(zhí)行的數(shù)據(jù)競(jìng)態(tài)PR #14014 修復(fù)了join 引擎原語(yǔ)在 OLAP 流式streaming模式執(zhí)行時(shí)的數(shù)據(jù)競(jìng)態(tài)。對(duì)應(yīng)代碼位于 go/vt/vtgate/engine/join.goTryStreamExecuteL123 起在流式執(zhí)行時(shí)引入了sync.MutexL125-127確保并發(fā)讀取 join 兩翼結(jié)果集時(shí)共享狀態(tài)的一致性。該修復(fù)對(duì)大規(guī)模聚合/Join 分析查詢OLAP 工作負(fù)載的穩(wěn)定性有直接價(jià)值——此前在高并發(fā)流式場(chǎng)景下可能出現(xiàn)計(jì)劃執(zhí)行器狀態(tài)被并發(fā)修改導(dǎo)致的非確定性結(jié)果或 panic。代價(jià)模型將 subshard opcode 納入 costPR #14025 修復(fù)了 vtgate 代價(jià)cost計(jì)算未包含 subshard opcode 的問(wèn)題。在 v3 規(guī)劃器中路由 opcode如EqualUnique、IN、Subshard等決定查詢發(fā)往分片的方式。若代價(jià)計(jì)算遺漏Subshard這一 opcode規(guī)劃器可能高估或低估某些查詢的代價(jià)進(jìn)而選擇次優(yōu)的執(zhí)行計(jì)劃例如錯(cuò)誤地合并/拆分查詢、選擇錯(cuò)誤的 route 方式。修復(fù)后代價(jià)估算更貼近真實(shí)執(zhí)行開銷有利于在跨分片場(chǎng)景下選出更合理的計(jì)劃。TabletManager半同步動(dòng)作枚舉的全量覆蓋PR #13957 修復(fù)了convertBoolToSemiSyncAction方法未能覆蓋全部半同步動(dòng)作的問(wèn)題。該方法位于 go/vt/vttablet/tabletmanager/rpc_actions.go L194-214func (tm *TabletManager) convertBoolToSemiSyncAction(ctx context.Context, semiSync bool) (SemiSyncAction, error) { semiSyncExtensionLoaded, err : tm.MysqlDaemon.SemiSyncExtensionLoaded(ctx) if err ! nil { return SemiSyncActionNone, err } switch semiSyncExtensionLoaded { case mysql.SemiSyncTypeSource, mysql.SemiSyncTypeMaster: if semiSync { return SemiSyncActionSet, nil } else { return SemiSyncActionUnset, nil } default: if semiSync { return SemiSyncActionNone, vterrors.VT09013() } else { return SemiSyncActionNone, nil } } }半同步動(dòng)作枚舉定義在同文件 L47-53SemiSyncActionNone、SemiSyncActionSet、SemiSyncActionUnset。修復(fù)前該方法在某些 MySQL/分支的半同步插件狀態(tài)SemiSyncType變體下無(wú)法正確映射出Set/Unset動(dòng)作導(dǎo)致在主從切換PlannedReparentShard / EmergencyReparentShard或備份恢復(fù)流程中半同步配置無(wú)法按預(yù)期啟停。修復(fù)后當(dāng)半同步插件以 source/master 類型加載時(shí)布爾值正確映射為SemiSyncActionSet或SemiSyncActionUnset其他情況下插件未加載或類型未知若請(qǐng)求開啟半同步則返回VT09013錯(cuò)誤若請(qǐng)求關(guān)閉則安全返回None。該方法的調(diào)用點(diǎn)包括 rpc_actions.go 的ChangeType流程L129以及 rpc_backup.goL172備份結(jié)束恢復(fù)原類型時(shí)和 rpc_replication.goL313。對(duì)于依賴半同步保證數(shù)據(jù)不丟失的集群這一修復(fù)直接關(guān)系到切換與恢復(fù)流程中的復(fù)制安全。Cluster ManagementBackupShard 使用自身標(biāo)志PR #13818 修復(fù)了BackupShard從**自身標(biāo)志flags**而非外部默認(rèn)值獲取選項(xiàng)的問(wèn)題。BackupShard是 vtctld 暴露的 RPC請(qǐng)求結(jié)構(gòu)定義見(jiàn) go/vt/proto/vtctldata/vtctldata.pb.go 的BackupShardRequest請(qǐng)求字段包括allow_primary、concurrency、upgrade_safe、incremental_from_pos、mysql_shutdown_timeout、init_sql等。修復(fù)前BackupShard在構(gòu)造備份請(qǐng)求時(shí)可能讀取了錯(cuò)誤來(lái)源的參數(shù)例如 vtctld 進(jìn)程級(jí)標(biāo)志或默認(rèn)值導(dǎo)致通過(guò) RPC 觸發(fā)的備份與命令行觸發(fā)的備份行為不一致——例如并發(fā)度、是否允許主庫(kù)備份等選項(xiàng)未按調(diào)用方意圖生效。修復(fù)后每次BackupShard調(diào)用都嚴(yán)格以其請(qǐng)求參數(shù)為準(zhǔn)保證vtctldclient BackupShard與內(nèi)部調(diào)用語(yǔ)義一致。CI/Build、工程化與發(fā)布流程改進(jìn)v15.0.5 的工程化改進(jìn)同樣值得關(guān)注靜態(tài)檢查覆蓋 changelog 目錄PR #14004Static Code Checks Etc現(xiàn)在會(huì)在./changelog目錄過(guò)期如未生成新版本變更記錄時(shí)讓 CI 失敗從流程上強(qiáng)制每個(gè)發(fā)布分支維護(hù)變更記錄這也是本文檔所在目錄能保持結(jié)構(gòu)一致的原因啟用 e2e 競(jìng)態(tài)檢測(cè)失敗PR #14009tools/e2e_test_race.sh現(xiàn)在允許競(jìng)態(tài)檢測(cè)失敗直接中斷 CI并修復(fù)了一批已知競(jìng)態(tài)與本次多處 data race 修復(fù)形成呼應(yīng)升級(jí)測(cè)試 Go 版本到 go1.20.8PR #13938release-15.0 分支的升級(jí)測(cè)試環(huán)境更新至 Go 1.20.8vtorc 專用容器PR #14145docker 目錄新增專門的 vtorc 容器鏡像vtorcVitess 拓?fù)浠謴?fù)控制器不再需要依賴通用鏡像手工組裝docgen 嵌入 commit IDPR #14072與homedir 匿名化PR #14104自動(dòng)生成的文檔 frontmatter 中嵌入 commit ID并對(duì)文檔中的用戶主目錄路徑做匿名化處理提升文檔可追溯性與隱私性CI 穩(wěn)定性PR #14118、#14120在 reparent 測(cè)試 teardown 中刪除 VTDATAROOT 殘留文件以消除測(cè)試相互污染并在找到安全方案前移除 FOSSA 測(cè)試。升級(jí)建議與風(fēng)險(xiǎn)提示Online DDL 語(yǔ)義變化需重點(diǎn)回歸--postpone-completion對(duì)即時(shí)操作CREATE/DROP 等生效范圍的擴(kuò)大可能改變現(xiàn)有自動(dòng)化流程對(duì)遷移何時(shí)完成的預(yù)期若你的流程依賴遷移完成時(shí)間點(diǎn)觸發(fā)后續(xù)動(dòng)作升級(jí)后建議先在測(cè)試環(huán)境驗(yàn)證 DROP/CREATE 類遷移的行為半同步修復(fù)直接影響切換安全convertBoolToSemiSyncAction的全量覆蓋意味著主從切換、備份恢復(fù)流程中半同步啟停行為更規(guī)范但若集群使用了非標(biāo)準(zhǔn)半同步插件加載方式需關(guān)注VT09013錯(cuò)誤是否會(huì)因semiSynctrue請(qǐng)求而暴露產(chǎn)物清理策略可下放到遷移級(jí)借助--retain-artifactsduration可針對(duì)大表或?qū)徲?jì)需求差異化設(shè)置影子表保留時(shí)長(zhǎng)同時(shí)取消/失敗遷移的產(chǎn)物將不再無(wú)限滯留查詢服務(wù)穩(wěn)定性提升join OLAP 流式執(zhí)行與 schema tracker 的競(jìng)態(tài)修復(fù)對(duì)高并發(fā)分析查詢和 schema 頻繁變更的集群收益明顯。參考文件索引版本變更記錄changelog/15.0/15.0.5/changelog.mdOnline DDL 執(zhí)行器與策略語(yǔ)義go/vt/vttablet/onlineddl/executor.goOnline DDL 內(nèi)部表 SQL 與清理邏輯go/vt/vttablet/onlineddl/schema.go半同步動(dòng)作映射修復(fù)go/vt/vttablet/tabletmanager/rpc_actions.go半同步在備份/復(fù)制流程中的調(diào)用go/vt/vttablet/tabletmanager/rpc_backup.go、go/vt/vttablet/tabletmanager/rpc_replication.gojoin 引擎流式執(zhí)行競(jìng)態(tài)修復(fù)go/vt/vtgate/engine/join.goBackupShard RPC 請(qǐng)求定義go/vt/proto/vtctldata/vtctldata.pb.go【免費(fèi)下載鏈接】vitessVitess is a database clustering system for horizontal scaling of MySQL.項(xiàng)目地址: https://gitcode.com/gh_mirrors/vi/vitess創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考