全部產品
Search
文件中心

PolarDB:熱點行最佳化

更新時間:Aug 08, 2024

本文將介紹熱點行效能最佳化功能。

前提條件

PolarDB叢集版本需為以下版本之一:

  • PolarDB MySQL版5.6版本且核心小版本需為20200601及以上。

  • PolarDB MySQL版5.7版本且核心小版本需為5.7.1.0.17及以上。

  • PolarDB MySQL版8.0版本且核心小版本需為8.0.1.1.10及以上。

  • 為了確保熱點行效能最佳化功能正常運作,需要開啟PolarDB MySQL版資料庫的Binlog功能

    • 開啟Binlog功能後會導致寫效能下降。

    • 開啟Binlog功能後相應的儲存也會增加。

說明

關於如何升級核心小版本請參見小版本升級

背景資訊

熱點行面臨以下問題:

  • 資料庫中那些會被頻繁執行增刪改查操作的資料行稱為熱點行。當一個事務對一行資料進行更新時,會對目標資料行加鎖,直到事務提交或復原時才釋放。同一時段內,對於同一個資料行,只有一個事務能夠進行更新,其它事務需要等待。由此可見,對單一熱點行的更新要求其實是串列執行的,傳統的分庫分表策略在效能提升方面並不會有太大協助。

  • 在電商平台業務中,限購、秒殺是常用的促銷手段。在這些情境下,大量對熱點行的更新要求在極短時間間隔內到達後台資料庫系統,必然造成嚴重的行鎖競爭和等待,影響系統效能。如果一個更新要求等待執行的時間變長,將會對業務層面產生顯著負面影響。

針對上述問題,單純提高電腦硬體設定已經無法滿足這樣的低延遲需求。因此PolarDB在資料庫核心層進行了創新性的最佳化,不但能夠自動識別熱點行更新要求,而且將一定時間間隔內對同一資料行的更新操作進行分組,不同分組採用流水線的方式平行處理,通過這些最佳化,極大地提升了系統的效能。具體方案如下:

  • 串列處理變流水線處理

    為了提升資料庫系統的效能,最直接的方法是使用平行處理,但是對同一熱點行的更新操作很難做到完全並行,PolarDB創新性地使用了流水線處理方式,最大限度地將熱點行更新操作並行化。

    1

    熱點行更新操作所使用的SQL語句會用autocommit或者commit_on_success進行標記,最佳化後的MySQL核心層會自動識別帶此類標記的更新操作,在一定的時間間隔內,將收集到的更新操作按照主鍵或者唯一鍵進行Hash,對於Hash到同一個桶中的更新操作,會將它們按照到達的先後順序分組分批地進行處理和提交。

    為了使用流水線方式處理這些更新操作,需要使用兩個執行單元對它們進行分組。當第一個分組收集完畢準備提交時,第二個分組立即開始收集更新操作;當第二個分組收集完畢準備提交時,第一個分組已經提交完畢並開始收集新一批的更新操作,兩個分組不斷切換,並存執行。

    現如今多核CPU的使用已經非常普遍。這樣的流水線式的處理方式能夠充分利用硬體資源,提升CPU的使用率,提高資料庫系統的平行處理能力,從而最大限度地提升資料庫系統的輸送量。

  • 消除申請行鎖時的等待

    為了保證資料的邏輯一致性,對一個資料行進行更新時,首先會對該資料行加鎖。如果加鎖請求無法立刻滿足,則進入等待狀態,這樣一來,不但增加了處理延遲,而且還會觸發死結檢測,導致額外的資源消耗。

    前面提到,我們會按照時間順序將對同一資料行的更新操作進行分組,組內第一個更新操作為Leader,其讀取目標資料行並且加鎖,後續更新操作為Follower,對目標資料行加鎖時,如果發現Leader已經持有行鎖,不需要等待,直接獲得行鎖。

    通過這個最佳化,能夠減少行鎖的加鎖次數和時間開銷,整個資料庫系統的效能有了顯著的提升。

  • 減少B-tree索引的遍曆

    MySQL是以B-tree索引的方式管理資料的,每次執行查詢時,都需要遍曆索引才能定位到目標資料行,資料表越大,索引層級越多,遍曆時間就越長。

    在前面提到的對更新操作進行分組的機制中,只有每組的Leader遍曆索引定位元據行,之後把更新後的資料行緩衝(Row Cache)在記憶體中,同組的Follower加鎖成功後,直接從記憶體中讀取目標資料行,而不需要再次遍曆索引。

    這樣一來,從整體上減少了索引遍曆的次數和時間開銷。

使用限制

在以下情境中,熱點行效能最佳化將不會被使用:

  • 熱點行所屬的資料表是分區表。

  • 熱點行所屬的資料表上定義了觸發器(Trigger)。

  • 熱點行使用了Statement Queue機制。

使用方法

  • 使用熱點行效能最佳化功能前,您需要對如下參數進行配置。如何配置參數,詳細操作請參見設定叢集參數和節點參數

    參數

    說明

    loose_hotspot

    熱點行效能最佳化總開關,取值為ON或OFF,預設值為OFF。

    loose_hotspot_for_autocommit

    Auto-commit模式下的UPDATE語句能否使用熱點行效能最佳化,取值為ON或OFF,預設值為OFF。

    說明

    只有當hotspot為ON時,才支援配置該參數。

    loose_hotspot_update_max_wait_time

    行資料分組批次更新(Group Update)過程中Leader等待Follower加入該分組的等待時間,單位為微秒(us),預設值為100us。

    loose_hotspot_lock_type

    行資料分組批次更新過程中是否使用新類型的行鎖,取值為ON或OFF,預設值為OFF。

    說明

    該參數開啟時,對相同熱點行的更新操作申請行鎖時不需要等待,從而提升效能。

    說明
    • hotspot_for_autocommithotspot_update_max_wait_timehotspot_lock_type參數暫不支援使用者在控制台上進行修改。如有修改需求,請前往配額中心,在配額名稱PolarDB熱點行參數調整操作列,單擊申請來申請修改參數值。

    • 熱點行效能最佳化需要依賴Binlog,所以,當Binlog功能處於關閉狀態時,試圖開啟參數hotspot時會失敗並報錯。

      當Binlog處於關閉狀態時,試圖使用MySQL [(none)]> set global hotspot=ON;命令開啟參數hotspot時會失敗,並出現如下報錯:

      ERROR 3042 (HY000):
      Variable 'hotspot' cannot be enabled because 'bin logging' is enabled/disabled

      如何開啟Binlog,詳細操作步驟請參見開啟Binlog

    • 當全域Binlog開啟,但是會話層級的Binlog關閉時,可以開啟參數hotspot,但是執行UPDATE語句時並不會使用熱點行效能最佳化。

    • 當參數rds_ic_reduce_hint_enable處於開啟狀態時,試圖使用MySQL [(none)]> set global hotspot=ON;命令開啟參數hotspot時會失敗,並出現如下報錯:

      ERROR 3042 (HY000): Variable 'hotspot' cannot be enabled because 'rds_ic_reduce_hint_enable' is enabled/disabled
  • 您可以使用如下命令查看參數配置:

    show variables like "hotspot%";

    返回結果樣本

    +------------------------------+-------+
    |
    Variable_name                | Value |
    +------------------------------+-------+
    |
    hotspot                      | OFF |
    |
    hotspot_for_autocommit       | OFF |
    |
    hotspot_lock_type            | OFF |
    |
    hotspot_update_max_wait_time | 100 |
    +------------------------------+-------+
  • 熱點行最佳化功能涉及到三種新的最佳化器Hint:

    Hint

    是否必選

    說明

    COMMIT_ON_SUCCESS

    必選

    更新成功時提交。

    ROLLBACK_ON_FAIL

    可選

    更新失敗時復原。

    TARGET_AFFECT_ROW(1)

    可選

    顯式指定該請求只會更新一行,若不符合,更新失敗。

  • 您可以使用如下命令查看熱點行效能最佳化使用方式:

    show global status like 'Group_update%';

注意事項

由於Hint生效會自動認可事務,因此Hint需要位於事務的最後一條SQL語句。

效能測試

  • 測試所需如下資料表定義和測試語句:

    • 資料表定義

      CREATE TABLE sbtest (id INT UNSIGNED NOT NULL,c BIGINT UNSIGNED NOT NULL,PRIMARY KEY (id));
    • 測試語句

      UPDATE COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) sbtest SET c=c+1 WHERE id = 1;
  • 測試載入器:Sysbench

  • 測試情境和測試結果

    • 測試情境1:單個熱點行加8核CPU。

      測試結果:在單熱點行加8核CPU的情境下,引入熱點行最佳化後,庫存熱點效能在高並發時提升近64倍。

      2

    • 測試情境2:單個熱點行加32核CPU

      測試結果:在單熱點行加32核CPU的情境下,引入熱點行最佳化後,峰值QPS提升了63倍;高並發為8000時,效能提升了46倍。

      2

    • 測試情境3:8個熱點行加32核CPU

      測試結果:在多熱點行(8個)加32核CPU的情境下,引入熱點行最佳化後,峰值QPS提升了20倍。

      且當高並發達到16000時,在未使用熱點行最佳化功能的情況下,更新操作會導致資料庫出現故障無法返回更新操作結果;但使用熱點行最佳化後,更新操作可以正常返回,且QPS維持穩定。

      4