OneSQL :: 从Oracle那边学来的异步事务提交模式,提升MySQL数倍事务性能!

在管理支付系统时,曾经有两个数据库集群,对写入能力的要求非常高,其中一个是记录用户轨迹的CTU事件库,即记录用户在支付系统里的每一个动作,包括操作的IP地址、Mac地址等,然后在每一次重要操作(比如转账、提现等)之前,要在50ms之内去检查最近的用户轨迹数据,进行风险判断,比如是否被木马控制等等。最开始使用单个Oracle数据库来支持,由于每笔交易状态变更和每次登录都有数次数据写入,写入压力远远超过交易系统。另一个数据库叫产品账,其实是计数器,可以理解成按一定规则预计算好的用户轨迹,同样对于每一次登录和每一次交易状态变更,都要实时统计不同唯度的统计数值,因此数据库的插入和更新操作都很频繁,写入压力同样远超过交易系统。

开启数据库事务日志实时刷盘是必须的要求,MySQL中每秒钟刷一次是不满足要求的,应用的API性能也非常重要,要求插入和更新操作能快速返回。而Oracle 9i中的异步事务提交模式,同时满足数据持久化和性能的要求。在解决天猫秒杀问题时,同时想到了前面的两个业务场景,后来在OneSQL中设计了MySQL的独立日志同步线程,实现了类似Oracle异步提交的机制,以应对大量数据写入的场景。使得MySQL的事务在提交时,可以写入到内存,并唤醒日志同步线程,就返回给客户端,而不需要等待日志刷盘操作,使得客户端的响应时间不受后端IO抖动的影响。这个模式需要用如下参数显式开启:

tcc_async_commit_mode = on

默认是不开启的,即需要等事务日志刷盘后响应客户端,以保证客户端收到确认后的数据都是持久化的。来看一下这两种模式下测试结果,测试工具为sysbench(update_non_index.lua),并将所有的数据文件放到MemFS下进行(没有PCIE-Flash)。先来看一下启用异步提交的模式,测试结果(居然有26万TPS,CPU用尽12个核)如下所示:

[root@osd12 data]# sh bench.sh 96
sysbench 1.0:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 96
Initializing random number generator from current time


Initializing worker threads...

Threads started!

OLTP test statistics:
    queries performed:
        read:                            0
        write:                           15412127
        other:                           0
        total:                           15412127
    transactions:                        0      (0.00 per sec.)
    read/write requests:                 15412127 (256856.68 per sec.)
    other operations:                    0      (0.00 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          60.0028s
    total number of events:              15412127
    total time taken by event execution: 5731.9852s
    response time:
         min:                                  0.10ms
         avg:                                  0.37ms
         max:                                100.19ms
         approx.  95 percentile:               0.78ms

Threads fairness:
    events (avg/stddev):           160542.9896/2673.88
    execution time (avg/stddev):   59.7082/0.01

接下来再来看一下未启用异步提交的情况,测试结果(达到18万TPS)如下:

[root@osd12 data]# sh bench.sh 96
sysbench 1.0:  multi-threaded system evaluation benchmark

Running the test with following options:
Number of threads: 96
Initializing random number generator from current time


Initializing worker threads...

Threads started!

OLTP test statistics:
    queries performed:
        read:                            0
        write:                           10901770
        other:                           0
        total:                           10901770
    transactions:                        0      (0.00 per sec.)
    read/write requests:                 10901770 (181692.99 per sec.)
    other operations:                    0      (0.00 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          60.0010s
    total number of events:              10901770
    total time taken by event execution: 5741.4230s
    response time:
         min:                                  0.12ms
         avg:                                  0.53ms
         max:                                 20.41ms
         approx.  95 percentile:               1.05ms

Threads fairness:
    events (avg/stddev):           113560.1042/1696.63
    execution time (avg/stddev):   59.8065/0.00

即使在内存文件系统上,异步提交模式性能仍比普通模式快45%左右,如果在普通磁盘或存贮上,相对效果会更加明显,对于数据保护和性能要求都极高的场景,日志异步刷出将是很好的选择。在普通模式下,也可以对某个操作进行异步提交设置,如下所示:

update [skip_sync] sbtest ......

日志提交的顺序仍然保留,由于MySQL程序架构的特殊性,binlog日志的刷出和InnoDB日志的写出被移到了独立的线程中工作后,在IO链路比较长的存贮系统(如云盘、SATA、SAN等)中,事务处理性能得到极大提升。异步模式,在性能上等同于双零设置,如下所示:

sync_binlog = 0
innodb_flush_log_at_trx_commit=0

而在数据保护上则等同于双1的效果,如下所示:

sync_binlog = 1
innodb_flush_log_at_trx_commit=1

事实上要比双零设置好,由于binlog & innodb log file文件实时刷盘,不会存在OS脏页太多的问题,让数据库的运行更平稳,在OneSQL中master线程不再负刷磁盘工作,可以更好地处理其他的工作。