熱點行是指在數據庫中那些會被頻繁執行修改操作的數據行。高并發場景下對熱點行的更新會造成嚴重的行鎖競爭與等待,影響系統性能。因此PolarDB針對此場景在數據庫內核層進行了創新性的優化,極大地提升了系統性能。
背景信息
熱點行面臨以下問題:
當一個事務對一行數據進行更新時,會對目標數據行加鎖,直到事務提交或回滾時才釋放。在同一時段內,針對同一數據行,只有一個事務能夠進行更新,而其他事務則需要等待。由此可見,對于單一熱點行的更新請求實際上是串行執行的,傳統的分庫分表策略在性能提升方面并不會有太大幫助。
在電商平臺業務中,限購、秒殺是常用的促銷手段。在這些場景下,大量對熱點行的更新請求在極短時間間隔內到達后臺數據庫系統,必然造成嚴重的行鎖競爭和等待,影響系統性能。如果一個更新請求等待執行的時間變長,將會對業務層面產生顯著負面影響。
針對上述問題,單純提高計算機硬件配置已經無法滿足這樣的低延遲需求。因此PolarDB在數據庫內核層進行了創新性的優化,不但能夠自動識別熱點行更新請求,而且將一定時間間隔內對同一數據行的更新操作進行分組,不同分組采用流水線的方式并行處理,通過這些優化,極大地提升了系統的性能。
技術方案
串行處理變流水線處理
為了提升數據庫系統的性能,最直接的方法是使用并行處理,但是對同一熱點行的更新操作很難做到完全并行。PolarDB創新性地使用了流水線處理方式,最大限度地將熱點行更新操作并行化。
熱點行更新操作所使用的SQL語句會用
autocommit
或者COMMIT_ON_SUCCESS進行標記。優化后的MySQL內核層會自動識別帶此類標記的更新操作,在一定的時間間隔內,將收集到的更新操作按照主鍵或者唯一鍵進行Hash
,對于Hash
到同一個桶中的更新操作,會將它們按照到達的先后順序分組分批地進行處理和提交。為了使用流水線方式處理這些更新操作,需要使用兩個執行單元對它們進行分組。當第一個分組收集完畢準備提交時,第二個分組立即開始收集更新操作。當第二個分組收集完畢準備提交時,第一個分組已經提交完畢并開始收集新一批的更新操作,兩個分組不斷切換,并行執行。
現如今多核CPU的使用已經非常普遍。這樣的流水線式的處理方式能夠充分利用硬件資源,提升CPU的使用率和數據庫系統的并行處理能力,從而最大限度地提升數據庫系統的吞吐量。
消除申請行鎖時的等待
為了保證數據的邏輯一致性,對一個數據行進行更新時,首先會對該數據行加鎖。如果加鎖請求無法立刻滿足,則進入等待狀態。這樣一來,不但增加了處理延遲,還會觸發死鎖檢測,導致額外的資源消耗。
前面提到,我們會按照時間順序將對同一數據行的更新操作進行分組。組內第一個更新操作為Leader,其讀取目標數據行并且加鎖。后續更新操作為Follower,其對目標數據行加鎖時,如果發現Leader已經持有行鎖,無需等待,直接獲得行鎖。
通過這個優化,能夠減少行鎖的加鎖次數和時間開銷,整個數據庫系統的性能顯著提升。
減少B-tree索引的遍歷
MySQL是以B-tree索引的方式管理數據的。每次執行查詢時,都需要遍歷索引才能定位到目標數據行,數據表越大,索引層級越多,遍歷時間就越長。
在前面提到的對更新操作進行分組的機制中,只有每組的Leader遍歷索引定位數據行,之后把更新后的數據行緩存(Row Cache)在內存中。同組的Follower加鎖成功后,直接從內存中讀取目標數據行,不需要再次遍歷索引。
這樣一來,從整體上減少了索引遍歷的次數和時間開銷。
前提條件
PolarDB集群數據庫引擎需為以下版本之一:
MySQL 5.6,且內核小版本需為20200601及以上版本。
MySQL 5.7,且內核小版本需為5.7.1.0.17及以上版本。
MySQL 8.0,且內核小版本需為8.0.1.1.10及以上版本。
PolarDB MySQL版集群已開啟Binlog。
集群參數rds_ic_reduce_hint_enable處于關閉狀態。
關于如何升級內核小版本,請參見版本管理。
如何修改集群參數,請參見設置集群參數和節點參數。
集群參數在PolarDB控制臺上都已加上MySQL配置文件的兼容性前綴loose_。如果您需要在PolarDB控制臺修改rds_ic_reduce_hint_enable參數,請選擇帶loose_前綴的參數(即loose_rds_ic_reduce_hint_enable)進行修改。
使用限制
在以下場景中,熱點行性能優化將不會被使用:
熱點行所屬的數據表是分區表。
熱點行所屬的數據表上定義了觸發器(Trigger)。
熱點行使用了Statement Queue機制。
在全局Binlog開啟的情況下,若會話級別的Binlog關閉,執行
UPDATE
語句將不會使用熱點行性能優化。
使用說明
開啟熱點行性能優化功能。
您可以在PolarDB控制臺上修改以下參數,以開啟或關閉熱點行性能優化功能。
參數
說明
hotspot
熱點行性能優化功能總開關。取值范圍如下:
ON:開啟。
OFF(默認):關閉。
說明如何修改集群參數,請參見設置集群參數和節點參數。
集群參數在PolarDB控制臺上都已加上MySQL配置文件的兼容性前綴loose_。如果您需要在PolarDB控制臺修改hotspot參數,請選擇帶loose_前綴的參數(即loose_hotspot)進行修改。
使用Hint語法來使用熱點行性能優化功能。
Hint
是否必選
說明
必選
更新成功時提交。
可選
更新失敗時回滾。
可選
顯式指定該請求只會更新一行,若不符合則更新失敗。
說明由于Hint語法生效會自動提交事務,因此Hint需要位于事務的最后一條SQL語句。
示例:更新
sbtest
表中c
列的數值。UPDATE /*+ COMMIT_ON_SUCCESS ROLLBACK_ON_FAIL TARGET_AFFECT_ROW(1) */ sbtest SET c = c + 1 WHERE id = 1;
相關操作
自定義參數配置
PolarDB控制臺不支持對以下參數進行修改。如果您需要進行修改,請前往配額中心,在配額名稱為PolarDB熱點行參數調整的操作列,單擊申請。
參數 | 說明 |
hotspot_for_autocommit |
|
hotspot_update_max_wait_time | 行數據分組批量更新(Group Update)過程中Leader等待Follower加入該分組的等待時間。
|
hotspot_lock_type | 行數據分組批量更新(Group Update)過程中是否使用新類型的行鎖。取值范圍如下:
說明
|
查看參數配置
您可以使用如下命令查看熱點行性能優化功能的參數配置。
SHOW variables LIKE "hotspot%";
返回結果示例:
+------------------------------+-------+
|Variable_name | Value |
+------------------------------+-------+
|hotspot | OFF |
|hotspot_for_autocommit | OFF |
|hotspot_lock_type | OFF |
|hotspot_update_max_wait_time | 100 |
+------------------------------+-------+
查看使用情況
您可以使用如下命令查看熱點行性能優化功能的使用情況。
SHOW GLOBAL status LIKE 'Group_update%';
性能測試
測試所需的數據表定義和測試語句如下:
數據表定義
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:單個熱點行加32核CPU。
測試結果:在單熱點行加32核CPU的場景下,引入熱點行性能優化后,峰值QPS提升了63倍。高并發為8000時,性能提升了46倍。
測試場景3:8個熱點行加32核CPU 。
測試結果:在多熱點行(8個)加32核CPU的場景下,引入熱點行性能優化后,峰值QPS提升了20倍。
且當高并發達到16000時,在未使用熱點行性能優化功能的情況下,更新操作會導致數據庫出現故障無法返回更新操作結果。但使用熱點行性能優化后,更新操作可以正常返回,且QPS維持穩定。