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实例

说明

创建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_sizememtable向操作系统/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数目。不可修改
compactionxengine_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_hitFilter Block的命中次数。
xengine_block_cache_filter_missFilter Block的miss次数。
xengine_block_cache_hitBlock Cache的整体命中次数(data_hit + index_hit)。
xengine_block_cache_index_hit索引Block命中次数。
xengine_block_cache_index_miss索引Block miss次数。
xengine_block_cache_missBlock Cache整体Miss次数(data_miss + index_miss)。
xengine_block_cachecompressed_miss压缩的Block Cache Miss次数。
xengine_bytes_read读物理磁盘的字节数。
xengine_bytes_written写入物理磁盘的字节数。
xengine_memtable_hitMemtable命中次数。
xengine_memtable_missMemtable Miss次数。
xengine_number_block_not_compressed未压缩的Block数目。
xengine_number_keys_readKey的读取次数。
xengine_number_keys_updatedKey的更新次数。
xengine_number_keys_writtenKey的写入次数。
xengine_number_superversion_acquiresSuperversion引用的申请次数统计。
xengine_number_superversion_cleanupsSuperversion的清理次数。当一个Superversion无人再引用时则被清理。
xengine_number_superversion_releasesSuperversion的引用释放次数,当一个Superversion的引用次数为0时则被清理。
xengine_snapshot_conflict_errors在RR隔离级别下,因为Snapshot版本冲突而报错的次数。
xengine_wal_bytesRedo落盘字节数。
xengine_wal_group_syncsRedo执行GroupCommit的次数。
xengine_wal_syncedRedo日志Sync的次数。
xengine_write_other在事务流水线中,作为Follower完成提交的次数。
xengine_write_self在事务流水线中,作为Leader完成提交的次数。
xengine_write_wal写Redo日志的次数。