引言
TXSQL-Tencent MySQL 自从2016年5月份正式立项,在近一年的时间里对 MySQL 的读写性能、强同步、大并发量访问和稳定性等方面做了大量工作,读写性能在并发上升到一定程度时具有1倍以上的性能提升,同时在 TXSQL 的版本发展过程中修复了多个影响线上稳定性的 bug(如 redo 死锁,实例异常关闭、字符集引起的主备异常等),在保证了内核稳定的同时,对腾讯云的稳定性提供了有力的保障。 TXSQL 不仅提升了实例性能与稳定性,而且在发展的过程中积极和社区进行交流,在 DBAPlus 等社区发表了多篇具有影响力的文章,并作为演讲嘉宾,多次参与 ACMUG、DTCC、DBAPlus、开源中国和 InfoQ 全球架构师峰会等社区会议,大大提升了腾讯云在业界的影响力,赢得了客户的信任与口碑。
什么是 TXSQL,为什么要做 TXSQL ?
TXSQL 是 Tencent MySQL 的简称,是 TEG 基础架构部CDB (Cloud DataBase) 团队在近十年发展过程中衍生出来的一个对 MySQL 内核源码深度定制、对官方 MySQL 版本进行二次开发的项目。其主要目的是在保证线上稳定性的同时,满足业务对数据库的各种需求。TXSQL 的服务对象是公司内部用户和腾讯云上小至数G大至数百T的外部客户。TXSQL 是支撑这些业务平稳运行的关键基石,在服务用户的同时,以打造腾讯自己的MySQL分支为己任。
MySQL 作为最受欢迎的开源数据库,也是云上使用最多的数据库,不同的业务场景对数据库有不同的功能需求与性能需求,这样就决定了数据库本身的多样化需求,同时 MySQL 在不同使用场景下所衍生出来的各种问题,也影响着线上的稳定性,TXSQL 主要包括以下工作:
做为云上客户的服务者,我们必须有及时响应用户并解决各种问题的能力,也应该满足用户的各种合理要求,对内支持业务的快速发展,满足业务要求;对外为腾讯云提供强有力的竟争力,这就是 TXSQL 存在与发展的目的。
TXSQL 做了哪些事情
版本选择
其基准开发版本为 5.6.28, 选择 5.6.28 做为基准版本主要有以下原因:
综合以上原因,我们选择了 5.6.28 做为 TXSQL 开发的基准版本。
性能改进
read view 优化
read view 又称读视图,用于存储事务创建时的活跃事务集合。当事务创建时,线程会对 trx_sys 上全局锁,然后遍历当前活跃事务列表,将当前活跃事务的ID存储在数组中的同时,记录最大事务 low_limit_id & 最小事务 high_limit_id & 最小序列化事务 low_limit_no。 当事务执行时,凡是大于low_limit_id 的数据对于事务是不可见的,凡是事务小于 high_limit_id 的数据都是可见的,事务 ID 是 read_view 数组中的某一个时也是不可见的;Purge thread 在执行 Purge 操作时,凡是小于 low_limit_no 的数据,都是可以被 Purge 的,read view 是 MySQL MVCC 实现的基础;
由于read_view 的创建和销毁都需要获取 trx_sys->mutex, 当并发量很大的时候,事务链表会比较长,又由于遍历本身也是一个费时的工作,所以此处便成为了性能瓶颈,详情可以参考 ,为了解决这个问题 TXSQL 做了以下事情:
经过上述修改,读写性能都有很大的提升,详情可以参考文章 。
redo log group commit
MySQL 有两种很重要的 Log,分别为 redo log & binlog,前者是保证事务原子性操作所产生的日志,后者是主备数据同步所产生的同步日志。 其中 binlog 在 ordered_commit 时进行 group commit, 而 redo log 则是在事务提交的时候分别调用 trx_prepare 使 redo log 落地,导致 log_sys->mutex 竟争较为严重;从 crash recovery 的逻辑来看,只要 redo log 早于 binlog 落地,就不会有数据问题,因此在 ordered_commit 的第一阶段时,TXSQL 会收集各种引擎的最大的 redo log LSN,然后将小于该 LSN 的 redo log 落盘,从而提升写性能。更详细的分析与测试,可以参考 。
redo log 双缓冲区
MySQL redo log 是一个顺序写的单缓冲区,log_sys->mutex 锁资源竟争激烈,在事务落盘的过程中对 LSN 相关的读、写都被阻塞,为了解决 log_sys->mutex 的锁竟争问题,引入双缓冲区机制 & w_mutex 锁,在 flush redo log 的过程中释放 log_sys->mutex,继续持有 log_sys->w_mutex,从而阻塞写,不阻塞 LSN 相关的读操作,flush 完成后释放 w_mutex;从而提升并发性,提升性能。
adaptive hash index 锁拆分
MySQL 一次定位 cursor 的过程是从根结点到叶子结点的路径,时间复杂度为:height(index) + [CPU cost time],上述的两个优化过程无法省略定位 cursor 的中间结点,因此需要引入一种可以从 search info 定位到叶子结点的方法,从而省略根结点到叶子结点的路径上所消耗的时间,而这种方法即是 自适应索引(Adaptive hash index, AHI)。查询语句使用 AHI 的时候有以下优点:
AHI 的 btr_search_latch () & index lock 是 MySQL 中两个比较大的锁,详情可以参考 ,5.7 通过对 AHI 锁拆分 () 以及引入不同的索引锁协议 () 解决了这两个问题。但是 AHI 并不总能提升性能,在多表Join & 模糊查询 & 查询条件经常变化的情况下,此时系统监控 AHI 使用的资源大于上述的好处时,不仅不能发挥 AHI 的优点,还会为系统带来额外的 CPU 消耗,此时需要将 AHI 关闭来避免不必要的系统资源浪费,关于 AHI 的适应场景可以参考:。
TXSQL 则是和 5.7 的解决思路类似,只是使用的分区算法不同,关于自适应索引的详细说明可以参考:。
当然,以上这些只是我们所做优化的一部分,还有其它一些优化如 GTID 优化、强同步优化、针对业务所做的特殊优化等,这些优化都在线上发挥了不可小觑的作用,以后再以文章的方式一一给大家进行介绍。
功能添加
TXSQL 支持多种工作模式
TXSQL 根据配置的不同,支持不同的工作模式,分别为只读、读写、不可服务,在不同的模式下实例表现形式不同:
OSS 在实现跨园区容灾的时候会根据结点的角色设置不同的工作模式,从而避免双写的问题;
alter table ... nowait 功能
DDL 在执行过程中需要获取对应的表锁,然后进行操作,如果此时有事务获取表锁,则会造成此语句的阻塞,而后绪操作此表的请求也会被此 DDL 阻塞,因此我们引入了 Oracle 中的 alter table 超时失败的功能,即 alter table .... [nowait | wait for n] 的功能以降低 DDL 对线上的影响,oracle 中 select for update [nowait|wait for n] 则可以通过设置参数 innodb_lock_wait_timeout 来实现;
TXSQL 锁系统的扩展
MySQL 锁系统有两个特征:
TXSQL 对 MySQL的锁系统进行了扩展,实现了一种跨事务的、与连接无关的租约读写锁,用于应用层实现分布式事务,提供接口 cdb_lock, cdb_unlock 用于上锁与解锁请求,从而满足业务需求,详细接口介绍如下:
基于 semi-sync 的强同步
原生 semi-sync 存在着以下问题:
为了解决上面的问题并对强同步进行优化及显示状态信息,TXSQL 做了以下事情:
这些只是我们暂时做的,在以后的版本中,我们将会引入 thread pool、更完善的审记、防火墙等内部用户 & 云用户都需要的功能,随着时间的积累与版本的推移,TXSQL的功能将会越来越丰富。
稳定性改进与测试
稳定性是数据库服务首先要解决的问题,原生 MySQL 在稳定性方面存在着以下问题:
TXSQL 在服务业务的过程中不断的自我完善和发展,解决在发展过程中遇到的各种问题,如:
为了保证版本稳定性,TXSQL 对每一个 Patch 都有对应的 testcase 文件和覆盖率测试,对于比较重要的改动,不仅要有理有据,还会邀请 Oracle 官方人员进行必要的 Code Review; 每个小版本发布之前,都会进行回归测试、覆盖率测试、稳定性测试、性能测试以及压力测试,然后才会进行灰度发布;当然,对于每一次的版本发布,都有详细的 release notes 以供参考。
金融业务支持
数据的可靠性是金融业务必然的需求,由于 MySQL 自身存在的问题,很难保证数据的强一致性,这些问题包括:
为了解决上述问题并实现主备数据的强一致,TXSQL 结合 CDB 管控平台针对金融业务的需求,实现了以下特性:
除了数据强一制的支持,TXSQL 还实现了一套与连接无关的分布式锁来支持业务部门实现分布式事务,后绪随着对业务的深入,更多更好的金融特性将会在 TXSQL 中一 一实现,比如热点更新等;
版本表现
TXSQL 的首要发展目标是解决线上存在的问题并支持业务的稳健发展,同时在解决问题的过程中推动 TXSQL 自身的发展。
在近一年的发展过程中 TXSQL 共发布了 3 个版本,分别为 TXSQL_20160730、TXSQL_20160902 以及 TXSQL_20161130 版本,每个版本包含若干 issue,每个 issue 的紧迫程度决定其优先级,每一次版本发布都会对新版本的实例做严密的监控,以保证新版本的稳定性。下面我们从版本在线上的表现以及与官方数据的性能对比来对 TXSQL 做简单的介绍。
线上业务表现
TXSQL 与官方性能测试对比
TXSQL_0228 版本目前处于开发状态,所以我们选取了 TXSQL_20161130 版本与 TXSQL 的基准版本 MySQL 5.6.28、MySQL 5.6 的最新版本 5.6.35 以及 MySQL 5.7 的最新版本 5.7.17 做了性能对比,测试机器为 ts85, 测试详情如下:
测试说明
测试概况:测试结果为 sysbench 端统计出来的数据,其中 select.lua & update_index.lua 为单语句事务, oltp.lua 中包含10 个SQL语句,配置文件为:,测试数据为 100个表,每张表 10000条数据;
TXSQL 与各版本 select.lua 性能对比
TXSQL 与各版本 update_index.lua 性能对比
TXSQL 与各版本 oltp.lua 性能对比
从测试的过程与测试结果来看,TXSQL 不仅拥有更好的性能,还拥有更好的稳定性,在新的 ideas 不断实现的基础上,我们对 TXSQL 的表现拥有更多的期待。
TXSQL 的发展必然也应该是开放的,其特性来源并服务于用户,当版本内容丰富到一定程度时,我们会把 TXSQL 中不影响线上安全 & 非专利部分的代码进行开源,在没有开源之前,可以将安装包提供给公司内部有兴趣的同学进行对比测试,以增加大家对 TXSQL 的了解与支持。
关于 TXSQL 5.7
MySQL 5.7 自 GA 以来已经有1年有余,社区 & 用户的呼声也越来越高,TXSQL 会在今年上半年增加对 5.7 的支持,同时会对 5.7 的特性进行详细的分析以飨大家,另外在阅读代码 & 文档的过程中,笔者做了一些整理,希望对大家理解 5.7 有帮助;
其实,我们在 TXSQL 5.6 中做了很多 5.7 的事情,如 redo log 优化、read view 创建优化等,在新的 TXSQL 5.7 中,我们会有更多可以做的事情,比如执行计划缓存、比如写优化、再比如基于于 Group Replication 服务等等,我们相信 TXSQL 5.7 会是一个不俗的版本。
TXSQL 未来的发展发向
TXSQL 的发展只是刚刚起步,相比 percona, facebook 等这样的公司我们做的还远远不够,还有很多需要改进的空间,但路总是一步步走出来的,我们的差距也在讯速的缩小,在未来的发展过程中 TXSQL 仍然会以云用户为导向从以下方面不断的进行改进:
所以,大家在使用数据库的过程中如果有好的想法或者需求也可以和我们联系,我们会尽最大的努力来满足大家的需求,支持业务的发展。