全部產品
Search
文件中心

PolarDB:BlOB效能最佳化

更新時間:Sep 25, 2025

針對MySQL在高並發環境下寫入BLOB(二進位大對象)時常見的鎖競爭和Redo日誌瓶頸,PolarDB通過核心級最佳化,有效解決了BLOB寫入過程中的鎖爭用、I/O壓力及空間管理等問題,顯著提升了DML和DDL操作的效能,確保您的業務在高並發情境下穩定高效地運行。

功能簡介

BLOB(Binary Large Object)是資料庫中用於儲存圖片、文檔、長文本等大尺寸資料的欄位類型。在原生MySQL InnoDB引擎中,當資料行中的BLOB欄位超過特定大小時,會將其儲存在獨立的外部資料頁(Off-Page)中。這種機制雖然能處理巨量資料,但也帶來了三大效能挑戰:

  1. 並發寫入瓶頸:更新外部頁時會觸發悲觀鎖,導致同一時間內單表只允許一個線程執行BLOB寫入,嚴重限制了並發能力。

  2. I/O壓力劇增:大欄位會產生體積龐大的Redo日誌,如果磁碟I/O能力不足,日誌刷寫將成為瓶頸,阻塞前台寫入。

  3. 空間回收延遲:舊版本BLOB資料的清理(Purge)效率不高,可能導致儲存空間膨脹和效能下降。

PolarDB的BLOB最佳化功能正是為瞭解決上述問題,它在不改變您使用習慣的前提下,從核心層面對BLOB的寫入、更新和回收全鏈路進行最佳化。

計費說明

BLOB效能最佳化功能均為PolarDB核心內建功能,不收取任何費用。

最佳化BLOB寫入效能

如果您在業務高峰期遇到BLOB表的寫入輸送量瓶頸、並發寫入時延高的問題,通常是由於寫入鎖競爭導致的。PolarDB提供了預分配頁和索引鎖(Latch)最佳化來解決此問題。

預分配頁最佳化

該最佳化將BLOB的寫入過程分解為以下幾個步驟:

  1. 計算並一次性批量申請好所需的全部資料頁。

  2. 在無鎖狀態下完成資料拷貝,將BLOB內容填充到新申請的頁中。

  3. 通過一次樂觀鎖操作,將產生的資料頁鏈表掛載到索引記錄上。

在整個寫入過程中,只有初始的空間申請階段是互斥的,其餘耗時較長的資料拷貝等操作均允許其他BLOB寫入並發進行。此外,由於資料拷貝是在非臨界區完成,系統可以避免因單次寫入產生大量Redo日誌而佔滿緩衝區、導致寫入被阻塞的風險。最終,該機制將全域鎖的持有時間降至最低,從而大幅提升了並發寫入能力。

索引鎖(Latch)最佳化

對於包含小尺寸(8 KB以下)或混合尺寸BLOB欄位的表,原生MySQL在更新時,常因索引頁結構變更(SMO)而過早地放棄樂觀鎖,退化為低效的悲觀鎖模式,嚴重影響並發效能。Latch最佳化通過在樂觀路徑下完成更多工作,解決了這一瓶頸。該最佳化按以下步驟工作:

  1. 保持樂觀路徑:當檢測到可能需要更新BLOB欄位時,最佳化邏輯並不會立即切換到悲觀鎖。它會繼續持有衝突機率更低的共用鎖定(S-latch),保持在樂觀更新路徑。

  2. 預先構建並嘗試更新:在樂觀路徑下,它會預先構建更新所需的BLOB資料結構,並嘗試直接對索引頁進行修改。

  3. 判斷與提交/回退

    • 成功:更新後的記錄能夠滿足當前索引頁的空間要求,操作便在樂觀路徑下快速完成。

    • 失敗:例如頁面空間不足,最佳化會自動放棄本次嘗試,並無縫回退到原生MySQL的悲觀鎖路徑,由其完成整個更新操作,確保資料的一致性。

這種樂觀嘗試的機制,其核心優勢在於顯著提高了樂觀更新的成功率。它使得大量原本會退化為悲觀鎖的操作,能夠以更輕量、更高效的方式完成,從而大幅提升了在高並發下更新混合尺寸BLOB資料的吞吐能力。

開啟寫入最佳化

您可以前往PolarDB控制台配置與管理 > 參數配置頁面來查看並修改以下參數來開啟最佳化:

參數

說明

支援版本

innodb_blob_prepare_pages

開啟或關閉BLOB預分配頁最佳化。

取值範圍:

  • ON:開啟

  • OFF:關閉

  • MySQL 5.6:不支援

  • MySQL 5.7:核心小版本需為5.7.1.0.35及以上。

  • MySQL 8.0.1:核心小版本需為8.0.1.1.47及以上。

  • MySQL 8.0.2:不支援

innodb_blob_prepare_max_extern_size

設定BLOB預分配頁最佳化中單個BLOB列的最大長度。

innodb_blob_latch_optimize

開啟或關閉BLOB索引鎖(Latch)最佳化。

降低BLOB寫入的Redo日誌量

如果您的業務寫入大量BLOB資料,導致Redo日誌產生速度過快,成為系統I/O瓶頸,您可以通過開啟Redo壓縮功能來緩解壓力。

Redo壓縮是指在將BLOB相關的Redo日誌寫入日誌緩衝區(Log Buffer)之前,對其進行並行壓縮。這一過程能夠顯著減少Redo日誌的實際寫入量(根據測試效果平均減少40%-60%),從而降低儲存I/O的壓力,避免因Redo模組瓶頸對整體寫入效能產生影響。在資料庫進行崩潰恢複時,會自動解壓並應用這些日誌。

開啟Redo壓縮

您可以前往PolarDB控制台配置與管理 > 參數配置頁面來查看並修改以下參數來開啟最佳化:

參數

說明

支援版本

innodb_blob_redo_compress_algorithm

設定BLOB的Redo的壓縮演算法。取值範圍:

  • none(預設)

  • lz4

  • zstd

  • zlib

  • MySQL 5.6:不支援

  • MySQL 5.7:核心小版本需為5.7.1.0.39及以上。

  • MySQL 8.0.1:不支援

  • MySQL 8.0.2:不支援

innodb_blob_redo_compress_level

設定所選壓縮演算法的壓縮層級。

取值範圍:0~9,預設值為6。

加速刪除BLOB空間回收

若您在頻繁刪除或更新BLOB資料後,發現資料表空間回收緩慢、檔案持續膨脹,其根源在於原生MySQL的後台Purge進程效率低下。該進程在清理資料時,會先持有Index SX等核心鎖再讀取BLOB頁面。如果頁面不在記憶體中,就會在鎖的保護下觸發耗時的磁碟I/O操作,從而長時間阻塞表上的其他並行作業。PolarDB的Purge頁預讀取最佳化通過將I/O操作與加鎖過程分離,解決了這一瓶頸。該最佳化按以下步驟工作:

  1. 識別目標頁:在正式加鎖並開始清理之前,Purge進程會首先識別出需要回收的完整BLOB外部頁鏈表。

  2. 非同步預讀:發起非同步I/O請求,將那些尚未在記憶體中的目標頁面提前從磁碟載入到緩衝池(Buffer Pool)中。

  3. 快速清理:當所有頁面都已載入到記憶體後,Purge進程才會擷取Index SX等核心鎖,並快速地執行純記憶體中的頁面釋放和中繼資料修改操作。

Purge頁預讀機制主要避免了在持有鎖的臨界區內發生任何磁碟I/O操作。通過將耗時最長的I/O操作前置,使得鎖的持有時間被縮短到僅剩快速的記憶體操作部分。這不僅提升了BLOB資料的回收效率,防止了空間膨脹,更重要的是減少了後台清理對前台業務(如高並發寫入)的阻塞,從而提升了整個資料庫的並發效能和穩定性。

開啟Purge預讀

您可以前往PolarDB控制台配置與管理 > 參數配置頁面來查看並修改以下參數來開啟最佳化:

參數

說明

支援版本

innodb_purge_blob_read_ahead

開啟或關閉BLOB Purge過程中的頁預讀取最佳化。

取值範圍:

  • ON:開啟

  • OFF:關閉

全版本支援。

提升DDL執行效率

如果您需要對包含大量BLOB資料的表執行DDL操作(如ALTER TABLE),並且耗時過長,可以通過開啟DDL相關的BLOB最佳化來大幅縮短操作時間。

  • 預分配頁最佳化:由於BLOB欄位的溢出列會在主鍵上存在,因此在執行主表重建(rebuild)的DDL操作時,會涉及到BLOB欄位的寫入。預分配頁最佳化採用了一種更為直接和簡化的加鎖方式來寫入BLOB資料,從而避免了處理複雜並發衝突的開銷,顯著提升了重建效率。

  • Latch最佳化:由於並行DDL會將主鍵樹切分,多個背景工作執行緒不會操作同一個資料頁。該最佳化將分配新頁的操作獨立保護,使得其他動作可以並發執行,提升效率。

  • Redo最佳化

    1. 頁面彙總:在批量載入(bulk load)資料時,不再為每條記錄產生Redo,而是在一個資料頁寫滿後,將整個頁面的變更作為一條大的Redo記錄寫入,提升Redo操作效率。

    2. 彙總壓縮:對上述彙總後的大塊Redo進行壓縮,進一步降低DDL過程中的Redo日誌量。

開啟DDL最佳化

您可以前往PolarDB控制台配置與管理 > 參數配置頁面來查看並修改以下參數來開啟最佳化:

說明

以下表格中部分參數暫不支援您手動修改。若您有相關需求,請提交工單聯絡我們處理。

參數

說明

支援版本

innodb_blob_prepare_pages_in_ddl

在DDL過程中是否開啟大欄位最佳化。取值範圍如下:

  • OFF(預設)

  • ON

  • MySQL 5.6:不支援

  • MySQL 5.7:核心小版本需為5.7.1.0.39及以上。

  • MySQL 8.0.1:核心小版本需為8.0.1.1.50及以上。

  • MySQL 8.0.2:不支援

innodb_bulk_load_without_index_lock_enable

在DDL過程中是否開啟索引鎖最佳化。取值範圍如下:

  • OFF(預設)

  • ON

  • MySQL 5.6:不支援

  • MySQL 5.7:核心小版本需為5.7.1.0.39及以上。

  • MySQL 8.0.1:核心小版本需為8.0.1.1.47及以上。

  • MySQL 8.0.2:核心小版本需為8.0.2.2.30及以上。

innodb_bulk_load_page_grained_redo_enable

在DDL批量載入時是否開啟Redo頁面彙總。取值範圍如下:

  • OFF

  • ON(預設)

  • MySQL 5.6:不支援

  • MySQL 5.7:支援,無核心小版本限制。

  • MySQL 8.0.1:支援,無核心小版本限制。

  • MySQL 8.0.2:支援,無核心小版本限制。

innodb_bulk_load_redo_compress_algorithm

設定DDL批量載入時的Redo壓縮演算法。取值範圍:

  • none(預設)

  • lz4

  • zstd

  • MySQL 5.6:不支援

  • MySQL 5.7:核心小版本需為5.7.1.0.39及以上。

  • MySQL 8.0.1:不支援

  • MySQL 8.0.2:核心小版本需為8.0.2.2.30及以上。

innodb_bulk_load_redo_compress_enable

設定DDL過程中Redo壓縮的應用目標。取值範圍:

  • 0:none(預設)

  • 1:secondary index

  • 2:all

  • MySQL 5.6:不支援

  • MySQL 5.7:核心小版本需為5.7.1.0.39及以上。

  • MySQL 8.0.1:不支援

  • MySQL 8.0.2:核心小版本需為8.0.2.2.30及以上。

相關模組最佳化

在大輸送量的BLOB操作環境下,系統瓶頸也可能出現在其他模組。為了獲得更佳的效能,PolarDB同時結合其他最佳化措施:

  • 並行Redo非同步寫入:將Redo Buffer中的資料分區,通過多個線程並發地發出非同步I/O任務,大幅提升Redo日誌的寫入吞吐能力(實測可達4 GB/s)。

  • 檔案擴充最佳化:基於PolarDB的自研Distributed File System,資料表空間擴充操作僅需修改少量中繼資料,並去除了原生的檔案填0操作,使檔案擴充的耗時和鎖開銷不再成為瓶頸。

  • 無鎖刷髒:採用Shadow Page技術,在刷髒頁時先構建記憶體副本,釋放頁鎖後再用副本進行I/O操作,避免了因刷髒持有頁鎖而阻塞寫入請求。

效能測試資料

以下資料顯示了開啟 BLOB最佳化後在DML和DDL情境下的效能提升。

  • DML效能 在高並發情境下,針對100 KB和200 KB行長的插入和更新,PolarDB的最佳化方案能帶來近3倍的效能提升。結合Redo壓縮後,效能可提升4-5倍。 https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/ZWGl05mjKAxV5n34/img/90d3dc1c-ac8c-42e2-9ed4-591da6e78912.png

    https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/ZWGl05mjKAxV5n34/img/7889d665-866e-4c89-af5a-0b8ac34da846.png

  • DDL效能 對於一張40 GB的含BLOB欄位的表,開啟最佳化後,DDL寫入速率提升5-6倍,總耗時下降 84%。 https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/ZWGl05mjKAxV5n34/img/add6464a-20db-4d1f-b534-f1a8e39abc45.png