RDS MySQL 8.0启用全新的Lizard事务系统,本文介绍Lizard的详细内容。

背景信息

官方版本MySQL 8.0持续对Redo Log日志系统、Lock System锁系统进行优化,大幅提升了系统性能,但InnoDB存储引擎的事务系统,存在读写互相干扰、XA事务不够稳定等问题。为了更好的提升RDS MySQL数据库的吞吐能力,并支持分布式事务和全局一致性,RDS MySQL 8.0.22(小版本20201231)开始启用全新的事务系统,即Lizard事务系统,Lizard的优势主要体现在如下三个方面:

高并发场景提高性能

官方版本MySQL的InnoDB引擎使用的事务系统是一个全局结构,DML流程中事务状态的变更以及查询过程的读视图(Read View)都要访问全局事务系统,造成严重的读写干扰问题,大大限制了系统的吞吐能力。而Lizard事务系统,在查询过程中不再维护用于实现多版本并发控制(MVCC)的Read View,也就是不再访问事务系统,大幅提高MySQL使用多核CPU的能力,有效提升高并发读写混合场景下的事务吞吐能力。

官方版本MySQL和使用Lizard的RDS MySQL进行SysBench性能测试的结果如下:

  • 测试环境
    • CPU:96核(Intel(R) Xeon(R) Platinum 8163 主频2.5GHz)
    • MySQL配置:
      • innodb_buffer_pool_size:50 GB
      • sync_binlog = 0,即每次事务提交时,Binlog会写入缓存,但是不会立刻写入磁盘,会由操作系统决定何时写入磁盘。
      • innodb_flush_log_at_trx_commit = 2,即每次事务提交时,Redo日志会写入缓存,但是不会立刻写入磁盘,每秒会执行一次写入磁盘(flush)操作。
      说明 sync_binlog = 0innodb_flush_log_at_trx_commit = 2是为了减少了IO子系统的干扰,方便测试高并发场景下Lizard事务系统对多核CPU资源的利用,并且能消除并发争用( Concurrent Contention)。
    • 数据量:30 GB(20张表,每张表500万条记录)
  • 测试场景1:SysBench OLTP Read_onlytest1
    说明 相比官方版本MySQL,RDS MySQL的QPS最多提高42.2%。
  • 测试场景2:SysBench OLTP Read_writetest2
    说明 相比官方版本MySQL,RDS MySQL的QPS最多提高69.9%。
  • 测试场景3:SysBench OLTP Write_onlytest3
    说明 相比官方版本MySQL,RDS MySQL的QPS最多提高48.1%。

综合所有测试结果,使用Lizard事务系统的RDS MySQL能在高并发情况下,消除事务系统的热点,大幅提升系统的吞吐能力。

原生闪回查询

在RDS MySQL数据库日常运维的过程中,可能会遇到误操作或者非预期的数据修改操作,一旦提交就无法Rollback,Lizard事务系统支持原生的闪回查询(Flashback Query),能够指定某个时间点进行一致性查询。

Flashback Query的语法如下:

SELECT ... FROM tablename
  AS OF [SCN | TIMESTAMP] expr;

示例

  • 初始化数据
    mysql> CREATE TABLE tab (
        -> id int PRIMARY KEY AUTO_INCREMENT,
        -> version int,
        -> gmt_modify timestamp
        -> );
    
    mysql> INSERT INTO tab VALUES (1, 1, now()),(2, 1, now());
    
    mysql> COMMIT;
    
    mysql> SELECT * FROM tab;
    +----+---------+---------------------+
    | id | version | gmt_modify          |
    +----+---------+---------------------+
    |  1 |       1 | 2020-12-17 16:40:38 |
    |  2 |       1 | 2020-12-17 16:40:39 |
    +----+---------+---------------------+
  • 更新数据
    mysql> UPDATE tab SET version = version + 1, gmt_modify = now();
    
    mysql> COMMIT;
    
    mysql> SELECT * FROM tab;
    +----+---------+---------------------+
    | id | version | gmt_modify          |
    +----+---------+---------------------+
    |  1 |       2 | 2020-12-17 16:40:54 |
    |  2 |       2 | 2020-12-17 16:40:54 |
    +----+---------+---------------------+
  • 使用Flashback Query查询
    mysql> SELECT * FROM tab AS OF TIMESTAMP '2020-12-17 16:40:40';
    +----+---------+---------------------+
    | id | version | gmt_modify          |
    +----+---------+---------------------+
    |  1 |       1 | 2020-12-17 16:40:38 |
    |  2 |       1 | 2020-12-17 16:40:39 |
    +----+---------+---------------------+
    
    mysql> SELECT * FROM tab AS OF TIMESTAMP '2020-12-17 16:40:55';
    +----+---------+---------------------+
    | id | version | gmt_modify          |
    +----+---------+---------------------+
    |  1 |       2 | 2020-12-17 16:40:54 |
    |  2 |       2 | 2020-12-17 16:40:54 |
    +----+---------+---------------------+
    说明 如果查询的版本时间点太旧,此时undo记录已经被删除(Truncate),就会报错:ERROR 7546 (HY000): Snapshot too old

为了更好的使用Flashback Query,RDS MySQL提供三个参数来管理Flashback Query,说明如下。

类别INNODB_UNDO_RETENTIONINNODB_UNDO_SPACE_SUPREMUM_SIZEINNODB_UNDO_SPACE_RESERVED_SIZE
描述InnoDB存储引擎保留undo记录的最长时间,单位:秒。

保留的越久,Flashback Query能够支持的回档查询越久,但undo表空间所占用的存储空间也会快速上升。

InnoDB存储引擎保留的undo表空间的最大值,单位:MB。

超过这个值时,会忽略INNODB_UNDO_RETENTION强制清理undo记录。

InnoDB存储引擎预留的undo表空间大小,单位:MB。

在INNODB_UNDO_RETENTION设置有效(非零)的情况下,将使用这部分空间尽可能的多保留undo记录。

命令行格式--innodb-undo-retention=#--innodb-undo-space-supremum-size=#--innodb-undo-space-reserved-size=#
参数范围全局参数(Global)全局参数(Global)全局参数(Global)
是否动态参数
设置变量应用是否提示
数据类型IntegerIntegerInteger
默认值01024000
取值范围0~42949672950~42949672950~4294967295

XA事务和全局一致性

为了完整的支持XA事务和分布式全局一致性,Lizard事务系统支持外部传入全局事务提交号GCN(Global Commit Number),说明如下:

  • 事务提交过程中,支持传入GCN提交,即COMMT/XA COMMIT by GCN。
  • 语句查询过程中,支持传入GCN查询,提SELECT by GCN。

例如在最简单的分布式结构和场景下,维护一个全局授时服务器(TSO)节点,并购买三个RDS MySQL高可用版实例。

test5

示例命令如下:

  • Node 1节点
    XA BEGIN $xid;
    UPDATE account SET balance = balance + 10 WHERE user = '张三';
    XA END;
    XA PREPARE $xid;
    XA COMMIT $xid $GCN;
  • Node 2节点
    XA BEGIN $xid
    UPDATE account SET balance = balance - 10 WHERE user = '李四';
    XA END;
    XA PREPARE $xid;
    XA COMMIT $xid $GCN;
  • 查询语句
    • Node 1节点
      SELECT * FROM account AS OF GCN $GCN where user ='张三';
    • Node 2节点
      SELECT * FROM account AS OF GCN $GCN where user ='李四’;