RDS MySQL提供阿里云自研的X-Engine存儲引擎,支持事務并且可以大幅降低磁盤空間占用。
產品介紹
X-Engine是阿里云數據庫產品事業部自研的聯機事務處理OLTP(On-Line Transaction Processing)數據庫存儲引擎。作為自研數據庫PolarDB的存儲引擎之一,已經廣泛應用在阿里集團內部諸多業務系統中,包括交易歷史庫、釘釘歷史庫等核心應用,大幅縮減了業務成本,同時也作為雙十一大促的關鍵數據庫技術,挺過了數百倍平時流量的沖擊。
X-Engine是適用于大規模電子商務交易處理的優化存儲引擎,X-Engine團隊撰寫的論文 《X-Engine: An Optimized Storage Engine for Large-scale E-Commerce Transaction Processing》,詳細講述了X-Engine在數據庫存儲引擎領域所做的原創性工作,2019年被SIGMOD'19 Industrial Track接收。
與傳統的InnoDB引擎不同,X-Engine使用分層存儲架構(LSM-Tree)。分層存儲有兩個比較顯著的優點:
需要索引的熱點數據集更小,寫入性能更高。
底層持久化的數據頁是只讀的,數據頁采用緊湊存儲格式,同時默認進行壓縮,存儲成本更低。
除了LSM-Tree架構自身的優勢之外,X-Engine在工程實現上也進行了大量的創新,主要包含如下幾個方面:
利用先天性的優勢,持續優化寫入性能,X-Engine相比同為LSM-tree架構的Rocksdb,有超過10倍的性能提升。
在存儲層引入數據復用技術等,優化Compaction的性能,降低傳統LSM-tree架構中Compaction動作對系統資源的沖擊,保持系統性能平穩。
支持在同一實例中混合部署SSD/HDD等不同IO能力的存儲設備, 利用天然分層結構的特點,結合不同存儲硬件的IO讀寫性能,智能地進行數據的冷熱分離存儲,在不降低性能的前提下,降低綜合成本。
引入多個層級Cache,同時結合Cach回填和預取機制,利用精細化訪問機制和緩存技術,彌補傳統LSM-tree引擎的讀性能短板。
通過以上多方面的工程優化,X-Engine成為傳統InnoDB引擎的一個替代選項,既支持事務,同時又能夠顯著的降低業務存儲成本(依據數據特征,存儲空間可降低至10%~50%),特別適合數據容量巨大,同時又要保證一定事務讀寫性能的業務。
關于X-Engine引擎適用的業務場景請參見X-Engine最佳實踐。
前提條件
實例為RDS MySQL 8.0高可用系列或基礎系列。
購買RDS實例(X-Engine)
如果您需要使用X-Engine引擎,請在購買RDS實例時,基礎資源頁面選擇實例類型為MySQL 8.0,然后在實例配置頁面選擇存儲引擎為X-Engine(高壓縮率)。其他參數說明請參見快速創建RDS MySQL實例。
RDS MySQL 5.5、5.6、5.7的用戶如果需要使用X-Engine引擎,請遷移至RDS MySQL 8.0版本實例。詳情請參見RDS實例間的數據遷移。
創建X-Engine表
如果創建實例時設置了默認引擎為X-Engine,則建表時默認引擎就是X-Engine。您可以通過如下命令查看默認引擎:
show variables like '%default_storage_engine%';
當默認引擎是X-Engine時,建表語句無需指定存儲引擎。
表創建成功后,后續使用方法與InnoDB一樣,數據會存儲在X-Engine引擎。
實例上仍然可以創建InnoDB引擎的表,尤其是使用DTS遷移數據時,可能會出現遷移的表引擎仍然為InnoDB。解決方案請參見引擎轉換方案二。
使用限制
與InnoDB引擎共存時的資源分配限制
使用X-Engine引擎時,95%的內存會提供給X-Engine引擎用做寫入緩存和BlockCache以加速讀寫速度,留給InnoDB Buffer Pool的內存非常少,所以在X-Engine引擎的實例中盡量避免使用InnoDB引擎表存儲太多數據,否則會因為緩存命中率低而導致性能大幅降低。建議使用RDS MySQL 8.0時,所有的表都使用相同的引擎(X-Engine或InnoDB),避免兩種引擎混用。
引擎功能限制
X-Engine在引擎功能上有一些限制,其中部分功能尚在開發中。其他未列出的部分,默認其功能特性與InnoDB引擎相同。
分類
功能
X-Engine引擎
備注
SQL功能
外鍵
不支持
-
臨時表
不支持
-
分區表(partition)
不支持(所有partition相關創建及增刪改查操作均不支持)
-
Generated Column
不支持
-
Handler API
不支持
-
列屬性
最大列長度
(longblob/longtext/json)
32MB
-
GIS地理數據類型
所有GIS相關數據類型均不支持(包含geometry、point、linestring、polygon、multipoint、multilinestring、multipolygon、geometrycollection)
-
索引
哈希索引
不支持
-
空間索引
不支持(所有fulltext索引相關的創建,使用均不支持)
-
事務
事務隔離級別
2個隔離級別:
讀已提交(RC)
可重復讀(RR)
-
最大事務
32MB
更大事務的支持在開發中
Savepoint
不支持
-
XA事務
不支持
功能開發中
鎖
鎖粒度
支持表級別鎖
支持行級別鎖
不支持GAP鎖
-
Skip Locked
Lock Nowait
不支持
-
字符集支持
非索引列支持的字符格式
非索引列支持所有的字符集(校對規則)
-
索引列支持的字符格式
latin1(latin1_bin)
gbk(gbk_chinese_ci、gbk_bin)
utf8(utf8_general_ci、utf8_bin)
utf8mb4(utf8mb4_0900_ai_ci、utf8mb4_general_ci、utf8mb4_bin)
-
主從復制
Binlog格式
stmt/row/mixed
說明默認為row,采用stmt/mixed在特定并發場景可能存在數據安全性問題。
-
大事務功能限制
X-Engine目前不支持大事務。當一個事務修改的行數特別多時,X-Engine會使用commit in middle功能。例如用戶在一個事務中修改的行數超過10000行,X-Engine會在內部把該事務提交,并且重新開啟一個事務繼續服務當前用戶開啟的事務。但是commit in middle并不能遵循嚴格意義上的ACID,您在使用過程中需要注意。以下舉例說明:
用戶開啟一個事務插入大量數據,在插入的過程中,由于先提交了一部分數據,其它請求就可以訪問到插入的數據。
用戶開啟一個事務修改大量數據,回滾的時候,已經執行了commit in middle的事務無法回滾。
drop table t1; create table t1(c1 int primary key , c2 int)ENGINE=xengine; begin; call insert_data(12000); //插入12000行數據,觸發commit in middle,前10000行數據已經提交。 rollback;// 回滾只能把最后2000條數據回滾。 select count(*) from t1; // 這里仍然能夠查詢到10000條數據。 +----------+ | count(*) | +----------+ | 10000 | +----------+ 1 row in set (0.00 sec)
用戶開啟一個事務刪除或者修改大量數據時,會遺漏掉本事務修改的行。
drop table t1; create table t1(c1 int primary key , c2 int)ENGINE=xengine; call insert_data(10000); begin; insert into t1 values(10001,10001), (10002,10002); delete from t1 where c1 >= 0;// delete操作觸發commit in middle,導致delete操作沒有讀到本事務插入的行。 commit; select * from t1; +-------+-------+ | c1 | c2 | +-------+-------+ | 10001 | 10001 | | 10002 | 10002 | +-------+-------+ 2 rows in set (0.00 sec)
參數說明
在快速創建RDS MySQL實例時,可以選擇X-Engine為默認存儲引擎,也可以根據下表的參數說明調整參數模板以便適應自身業務。
類別 | 參數 | 說明 | 備注 |
性能 | xengine_arena_block_size | memtable向操作系統/jemalloc的外部內存管理系統申請新內存分配的單位。 | 啟動后只讀 |
xengine_batch_group_max_group_size | 事務流水線最大分組數。 | 啟動后只讀 | |
xengine_batch_group_max_leader_wait_time_us | 事務流水線最大等待時間。 | 啟動后只讀 | |
xengine_batch_group_slot_array_size | 事務流水線最大batch大小。 | 啟動后只讀 | |
內存 | xengine_block_cache_size | 讀block緩存的大小。 | 不可修改 |
xengine_row_cache_size | 行緩存的大小。 | 不可修改 | |
xengine_write_buffer_size | 單Memtable的最大大小。 | 不可修改 | |
xengine_block_size | 磁盤上數據block大小。 | 初始化后只讀 啟動后只讀 | |
xengine_db_write_buffer_size | 所有subtable的Active Memtable的總計大小限制。 | 不可修改 | |
xengine_db_total_write_buffer_size | 所有subtable的Active Memtable/Immutable memtable的總大小限制。 | 不可修改 | |
xengine_scan_add_blocks_limit | 每個請求在范圍掃描時,可以加到BlockCache中的Block數目。 | 不可修改 | |
compaction | xengine_flush_delete_percent_trigger | 當Memtable中記錄數超過此數目時,則xengine_flush_delete_record_trigger參數生效。 | 不可修改 |
鎖 | xengine_max_row_locks | 單SQL請求中,最大可以鎖定的行數。 | 不可修改 |
xengine_lock_wait_timeout | 鎖等待超時時間。 | 不可修改 |
運行狀態指標
下表為X-Engine的運行狀態指標。
指標名 | 含義 |
xengine_rows_deleted | 刪除行數。 |
xengine_rows_inserted | 寫入行數。 |
xengine_rows_read | 讀取行數。 |
xengine_rows_updated | 更新行數。 |
xengine_system_rows_deleted | 對引擎為X-Engine的系統表的刪除次數。 |
xengine_system_rows_inserted | 對引擎為X-Engine的系統表的插入次數。 |
xengine_system_rows_read | 對引擎為X-Engine的系統表的讀取次數。 |
xengine_system_rows_updated | 對引擎為X-Engine的系統表的更新次數。 |
xengine_block_cache_add | 向Block Cache添加次數。 |
xengine_block_cache_data_hit | 讀數據Block命中Cache次數。 |
xengine_block_cache_data_miss | 讀數據Block時Miss次數。 |
xengine_block_cache_filter_hit | Filter Block的命中次數。 |
xengine_block_cache_filter_miss | Filter Block的miss次數。 |
xengine_block_cache_hit | Block Cache的整體命中次數(data_hit + index_hit)。 |
xengine_block_cache_index_hit | 索引Block命中次數。 |
xengine_block_cache_index_miss | 索引Block miss次數。 |
xengine_block_cache_miss | Block Cache整體Miss次數(data_miss + index_miss)。 |
xengine_block_cachecompressed_miss | 壓縮的Block Cache Miss次數。 |
xengine_bytes_read | 讀物理磁盤的字節數。 |
xengine_bytes_written | 寫入物理磁盤的字節數。 |
xengine_memtable_hit | Memtable命中次數。 |
xengine_memtable_miss | Memtable Miss次數。 |
xengine_number_block_not_compressed | 未壓縮的Block數目。 |
xengine_number_keys_read | Key的讀取次數。 |
xengine_number_keys_updated | Key的更新次數。 |
xengine_number_keys_written | Key的寫入次數。 |
xengine_number_superversion_acquires | Superversion引用的申請次數統計。 |
xengine_number_superversion_cleanups | Superversion的清理次數。當一個Superversion無人再引用時則被清理。 |
xengine_number_superversion_releases | Superversion的引用釋放次數,當一個Superversion的引用次數為0時則被清理。 |
xengine_snapshot_conflict_errors | 在RR隔離級別下,因為Snapshot版本沖突而報錯的次數。 |
xengine_wal_bytes | Redo落盤字節數。 |
xengine_wal_group_syncs | Redo執行GroupCommit的次數。 |
xengine_wal_synced | Redo日志Sync的次數。 |
xengine_write_other | 在事務流水線中,作為Follower完成提交的次數。 |
xengine_write_self | 在事務流水線中,作為Leader完成提交的次數。 |
xengine_write_wal | 寫Redo日志的次數。 |