首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MySQL 半同步複制 rpl_semi_sync_master_timeout 參數導致性能災難的 Bug 分析與修復

     編輯:Java 綜合教學

MySQL 半同步複制超時參數導致性能急劇下降的 Bug 深度解析

現象背景

在部署基於 MySQL 原生復制的高可用系統時,發現一個反直覺的現象:當半同步復制降級為異步復制的超時時間 rpl_semi_sync_master_timeout 設置極大值 (如 300 天) 時,系統 QPS 會嚴重下降,與超時時間呈正比關係。這在高併發場景下會造成災難性後果。

壓測數據對比

rpl_semi_sync_master_enabledrpl_semi_sync_master_timeout (ms)QPS換算天數
ON2,147,483,64813.99約 248 天
ON2,147,483,648196.3約 24.8 天
ON2,147,483,6411251.67約 2.5 天
ON86,400,0002146.961 天
ON43,200,0003211.1712 小時
ON21,600,0003583.026 小時
ON10,000 (默認)3637.1610 秒
OFF-8926.76異步模式

數據清晰顯示:超時值越大,QPS 越低,呈線性負相關。

根因分析:源碼中的致命 while 循環

查閱 MySQL 源碼 plugin/semisync/semisync_master.cc 中的 ReplSemiSyncMaster::commitTrx() 方法:

unsigned long long diff_nsecs = start_ts.tv_nsec + (unsigned long long)wait_timeout_ * TIME_MILLION;
abstime.tv_sec = start_ts.tv_sec;
while (diff_nsecs >= TIME_BILLION) {  // 罪魁禍首!
    abstime.tv_sec++;
    diff_nsecs -= TIME_BILLION;
}
abstime.tv_nsec = diff_nsecs;

問題本質:代碼通過 while 循環將毫秒級超時轉換為秒和納秒。循環次數等於 wait_timeout_ 對應的秒數。設置 300 天約 25,920,000 秒,意味著每次事務提交都要執行 2500 萬次循環迭代,直接阻塞主線程導致性能崩潰。

修復方案:數學運算替代循環

將循環替換為等價的除法與取模運算,時間複雜度從 O(n) 降為 O(1):

// 修改前
start_ts.tv_nsec + (unsigned long long)wait_timeout_ * TIME_MILLION;
abstime.tv_sec = start_ts.tv_sec;
while (diff_nsecs >= TIME_BILLION) { ... }

// 修改後
start_ts.tv_nsec + ((unsigned long long)wait_timeout_ % TIME_THOUSAND) * TIME_MILLION;
abstime.tv_sec = start_ts.tv_sec + (unsigned long long)wait_timeout_ / TIME_THOUSAND;

驗證與部署步驟

  1. 修改源碼:編輯 plugin/semisync/semisync_master.cc 替換上述邏輯
  2. 重新編譯:
    cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql ... 其他選項
    make
    
  3. 替換插件:
    cp ./plugin/semisync/semisync_master.so /usr/local/mysql/lib/plugin/
    chown mysql:mysql /usr/local/mysql/lib/plugin/semisync_master.so
    
  4. 重啟 MySQL 生效

修復效果

修復後 QPS 穩定在 3700 左右,與 rpl_semi_sync_master_timeout 設置值無關,性能恢復正常。

官方追蹤

該 Bug 已提交 MySQL 官方:Bug #80651

核心教訓:看似無害的參數配置可能觸發算法級性能陷阱。任何涉及時間轉換、大數運算的邏輯都應警惕 O(n) 循環,優先考慮 O(1) 數學運算替代。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved