PolarDB MySQL版通過PolarTrans對高并發OLTP場景進行了優化。PolarTrans的核心技術之一是通過提交時間戳技術CTS來取代傳統的基于活躍事務列表方案。本文主要介紹了PolarTrans中CTS技術原理及優勢,以及標準場景下的性能測試結果。
版本要求
若要開啟全局一致性(高性能模式),PolarDB MySQL版集群版本需為以下版本之一:
8.0.2版本且內核小版本需為8.0.2.2.19及以上。
8.0.1版本且內核小版本需為8.0.1.1.29及以上。
5.7版本且內核小版本需為5.7.1.0.26及以上。
如何確認集群版本,請參見查詢版本號。
背景信息
目前主流的開源關系型數據庫如MySQL或者PostgreSQL,其事務狀態更新以及MVCC機制均是采用了基于活躍事務列表的方案。這種方案在高并發場景下會帶來嚴重的性能瓶頸,無法充分利用CPU多核并發處理事務的邏輯;其次,基于活躍事務列表方案在集群一致性讀、集群多點寫入以及Share-Nothing架構中的XA事務管理上存在天然的缺陷。
在PolarTrans中,事務狀態更新無需維護活躍事務列表,傳統的事務狀態的拷貝過程通過獲取當前集群的最大提交時間戳來替代。事務狀態的迭代、獲取、查詢(可見性判斷)等邏輯更加輕量化,同時PolarTrans將大部分的事務邏輯進行無鎖優化,對于讀寫混合場景、純寫場景都有較大性能提升。
PolarTrans CTS技術的核心數據結構為CTS log,事務狀態迭代、可見性判斷、事務活躍狀態等核心事務邏輯,都是通過CTS log來完成的。CTS log的數據結構如下圖所示:
全內存設計的CTS log由一段ring buffer
組成,事務通過trx_id
取模映射到其對應的slot
,每個slot
包含trx
指針和csn(事務提交序列號)。
技術優勢
寫事務啟動
原生事務系統在寫事務啟動時,需要通過
trx sys mutex
保護來分配事務ID,寫入活躍事務ID數組(rw_trx_ids
),維護活躍事務ID到trx
映射的集合(rw_trx_set
),以及讀寫事務鏈表(rw_trx_list
)等數據結構。在PolarTrans事務系統中,事務啟動時會注冊到CTS log,根據trx_id
取模分配相應的slot
,并將事務狀態設置為特殊的active標記即可,并且該過程可以做到無鎖化處理。寫事務提交
原生事務系統寫事務提交時,需要在
trx sys mutex
保護下, 查找rw_trx_ids
并移除對應的trx_id
,維護rw_trx_set
、rw_trx_list
等。在PolarTrans事務系統中,事務提交時分配提交時間戳并更新CTS log中對應的csn字段即可。read view
InnoDB的MVCC機制核心需要通過
read view
來控制數據的可見性,原生事務系統獲取read view
的過程同樣需要在trx sys mutex
保護下,拷貝活躍事務ID數組、當前最小活躍ID和最大事務ID。在進行可見性判斷時, 可能需要查找活躍事務ID數組來確定可見性。在讀寫沖突較為嚴重的場景下,讀寫事務和只讀事務都需要在mutex
保護下更新和拷貝當前事務狀態,維護代價極高,并且可見性判斷效率較低。在PolarTrans事務系統中,通過獲取事務系統的最大提交時間戳來代替原生read view
,同樣可以做到無鎖處理。在可見性判斷過程中, 您只需要對比只讀事務csn和行記錄的trx csn
即可。
開啟PolarTrans
全局一致性(高性能模式)功能開啟后,PolarTrans功能會默認打開。關于如何開啟全局一致性(高性能模式)功能,請參見如何開啟全局一致性(高性能模式)。
性能對比
在相同場景下,分別測試原生事務系統(關閉PolarTrans)和PolarTrans事務系統(開啟PolarTrans)的QPS。
測試環境
一個規格為88核710 GB的PolarDB MySQL版8.0版本集群版。
測試工具
Sysbench
測試數據量
88張表,每張表1200萬條記錄。
測試用例
使用以下Sysbench內置用例進行測試。
oltp_read_write
oltp_insert
oltp_update_index
oltp_update_no_index
oltp_read_only
測試結果及說明
從以下測試中可以看出,在讀寫或只寫場景下,PolarTrans事務系統對于數據庫整體性能有非常大的提升。在只讀場景下,整個數據庫的性能并沒有發生變化,只讀事務可以通過ReadView緩存來降低事務狀態拷貝過程中的加鎖開銷,所以PolarTrans事務系統相比原生事務系統并不會帶來明顯的性能提升。
oltp_read_write
oltp_insert
oltp_update_index
oltp_update_no_index
oltp_read_only