在有大事務的業務情境中,大事務提交時常會出現Binlog耗時過長、執行個體長時間不可寫或夯住(hang)的問題。RDS MySQL引入的Binlog Cache Free Flush功能,最佳化了大事務提交的速度,解決了因大事務提交時間過長導致的執行個體抖動、長時間不可寫的問題,提升了執行個體的穩定性。
功能說明
由於Binlog的串列寫入機制,大事務不僅自身寫入Binlog緩慢,還會阻塞其他事務提交。本功能最佳化了大事務提交時的Binlog寫入機制,使提交速度不再受Binlog Event數量影響,始終保持高效。本功能解決了以下典型問題:
超大事務阻塞執行個體,導致其他事務無法及時提交。
大事務引發大量IO消耗,造成IO資源耗盡並拖慢查詢等業務。
大事務導致小事務執行變慢,引發活躍串連激增和效能抖動,嚴重時可能觸發雪崩效應導致執行個體不可用。
頻繁執行大事務持續引發業務流量的效能抖動。
前提條件
執行個體版本及核心小版本要求:
MySQL 8.0,小版本為20240731或以上。
MySQL 5.7,小版本為20240731或以上。
說明您可以在基本資料頁面的配置資訊地區查看是否有升級核心小版本按鈕。如果有按鈕,您可以單擊按鈕查看目前的版本;如果沒有按鈕,表示已經是最新版。詳情請參見升級核心小版本。
使用說明
建立執行個體:Binlog Cache Free Flush功能預設開啟。
存量執行個體:通過設定全域系統變數
loose_binlog_cache_free_flush可開啟該功能,參數修改後立即生效,無需重啟執行個體。相關參數:
loose_binlog_cache_free_flush_limit_size:開啟Binlog Cache Free Flush功能後,當事務的Binlog超過該參數值,提交時會將Binlog Cache臨時檔案轉為Binlog正式檔案。預設值:256 MB,取值範圍: 20971520~18446744073709551615 (單位:位元組)。
問題分析
當MySQL執行個體執行大事務時,慢查詢日誌可能記錄到某些本應快速完成的語句(如COMMIT)出現異常延遲。
原因是另一個線程的大事務因Binlog串列寫入機制導致資源競爭。大事務不僅自身寫Binlog耗時較長,還會阻塞其他事務的Binlog提交,引發全域序列化延遲。
運行sysbench oltp_write_only時,在每5秒執行一次產生512 MB Binlog的大UPDATE操作後,觀察到以下現象:
每次大
UPDATE提交時,TPS(每秒事務數)劇烈下降。抖動時間長度與Binlog大小正相關:事務產生的Binlog越大,對其他業務的延遲影響越顯著。
下圖直觀的展示了大事務對線上運行業務的影響。

UPDATE相關操作:
CREATE TABLE t_large (a INT, b LONGTEXT) ENGINE = InnoDB;
# 插入一行資料包含256 MB文本,UPDATE時產生的Binlog events是512 MB。
INSERT INTO t_large VALUES (1, repeat('a', 256000000));
UPDATE t_large SET a = a + 1;最佳化效果
TPS穩定性顯著提升:
最佳化前:每5秒一次的大
UPDATE導致TPS劇烈波動。最佳化後(橙色線):大
UPDATE對TPS的影響幾乎消除。

延遲無明顯波動:
不同大小的
UPDATE操作對時延的影響不再顯著(橙色線為最佳化後)。即使Binlog Events超過512 MB,其他事務提交的延遲未受明顯幹擾。

實現原理
Binlog Cache介紹
Binlog Cache是一塊會話層級的臨時空間,即為每一個會話建立一個Binlog Cache,用來暫存Binlog events。Binlog Cache由記憶體緩衝(Buffer)和臨時檔案(Temp File)兩部分組成,其中記憶體緩衝的大小由binlog_cache_size參數控制。當事務比較大,記憶體緩衝被寫滿之後,事務的events就會被記錄到臨時檔案中。
事務在執行過程中,會將自己產生的events暫存在Binlog Cache中。事務在提交時,需要按順序從Binlog Cache中讀出一個個Event,並且更新events的end_pos(結束位置)和checksum(校正和),然後將其寫到Binlog檔案中。為了保證事務在Binlog檔案中的連續性,整個過程是加鎖進行的,即一個事務寫Binlog檔案時,其他事務都會被阻塞。
大事務寫Binlog帶來的問題
對於非常大的事務,其使用的Binlog Cache可能會達到幾十個GB,在提交事務期間寫Binlog的過程耗時很長,並且對執行個體影響極大,主要包括以下兩點:
大事務寫Binlog過程中,會持有Binlog寫鎖,期間整個執行個體將處於不可寫狀態。
大事務寫Binlog的過程會消耗大量IO資源,在IO資源有限的情境下,可能導致整個執行個體夯住(hang)。
Binlog Cache Free Flush最佳化
AliSQL對Binlog Cache的臨時檔案進行了改造,使其具備了直接轉為Binlog檔案的能力。開啟本功能後,在大事務提交時會將Binlog Cache臨時檔案直接轉化為Binlog正式檔案,這個過程的耗時很短,並且IO資源消耗很少,徹底解決了大事務寫Binlog對執行個體的影響。
對Binlog Cache的改造
為了使Binlog Cache的臨時檔案能夠直接轉化為Binlog正式檔案,AliSQL對Binlog Cache的使用方式進行了改造。主要包括以下兩點:
在寫Binlog Cache的臨時檔案時,在檔案頭部預留出一部分空間。在臨時檔案轉Binlog正式檔案過程中,這部分空間用於存放Binlog頭部的events。
在寫Binlog Cache時,每個events都根據預留空間的大小計算自己的end_pos。
Binlog檔案的轉化
在大事務提交時,會直接將Binlog Cache臨時檔案轉化為Binlog正式檔案。在這個過程中,Binlog的檔案頭(File Header )和頭部的幾個events(Header Events)會填滿預留空間,預留空間主要包含四部分內容:
File Header:在每個Binlog檔案的頭部4位元組,都寫有一個標識:
[ 0xFE 'bin'],用來標識此檔案是個Binlog檔案。Header Events:包括Format description event和Previous gtid event。
Empty event:用來填充剩餘的預留空間的,使用當前Binlog中已有的ignorable event類型。
Gtid event:大事務的Gtid是在提交階段產生的,Gtid event也會被寫到預留空間中。
預留空間之後的Events in Binlog Cache,是Binlog Cache中的內容,主要包括Query event、Table map event、Row event和Xid event等。
與普通的Binlog檔案相比,使用本功能轉化而來的Binlog檔案有兩點區別:
多了一個Empty event。
預設關閉了本檔案的checksum。
Binlog Cache Free Flush功能不會改變Binlog的格式,基於Binlog的複製及第三方的工具不會受任何影響。