乐趣区

关于数据库:阿里云RDS深度定制XA-Crash-Safe

简介:近几年,随着分布式数据库系统的衰亡,特地是基于 MySQL 分布式数据库系统,会用到 XA 来保障全局事务的一致性。家喻户晓,MySQL 对 XA 事务的反对是比拟弱的,存在很多问题。为了满足分布式数据库系统对 XA 事务的要求,阿里做了大量的工作。本篇内容将从两局部介绍,第一局部介绍在 AliSQL 分支上做的一些实用功能;第二局部介绍 XA Crash Safe 问题的本源和在 5.7 和 8.0 版本上的实现原理。

一、阿里云 RDS MySQL(AliSQL)

AliSQL 是 MySQL 的分支,阿里在这个分支上做了很多深度的定制,以充沛开掘 MySQL 的后劲。AliSQL 撑持了阿里团体电商业务十余年,其稳定性、安全性和高性能是通过了极其严苛实际测验的。除此之外,AliSQL 做了很多实用性的性能,以进步 MySQL 的易用性和应用效率。下图是 AliSQL 上重要的性能的列表。

二、RDS 定制化性能介绍

1. 实用性:SQL Outline 在线固化 SQL 执行打算

咱们应用 MySQL 的时候时常会碰到一种状况,即业务跑着的时候有个 SQL 执行会变慢,剖析之后发现是这个 SQL 执行打算产生了变动。这种变动有很多起因,比方 bug 或是版本升级了等等。

MySQL 就提供了 hint 性能,它能够使咱们在 SQL 语句里减少一些提醒,以保障 SQL 在生成执行打算的时候是依照提醒来工作的。但这只是比拟理想化的状态,理论状况中这样是很不不便的,因为业务曾经在线上运行了,这个时候即便可能扭转业务的 SQL,也须要一个很漫长的工夫和过程。

为了解决这个问题,就有了 SQL Outline 的性能。这个性能不须要扭转利用的 SQL 语句,只须要在 server 端通知 RDS 碰到哪种类型的特定的 SQL,能够给它定制一个 hint,而后依照用户指定的形式执行。

2. 实用性:Performance Agent 可诊断、可度量

咱们在实例的监控上也做了大量的工作,从而能够很容易的剖析数据库中的一些问题。首先就是实例级别的统计信息,它包含了操作系统层面、server 层和 InnoDB 等共计 55 个指标。而后把它放到一个 Performance 表中,每秒钟进行一次统计。通过这些统计的信息能够剖析零碎呈现问题的起因。

3. 实用性:Performance Insight 可诊断、可度量

这个是对象级别性能度量的指标,包含表和索引。这些统计能够反对业务数据模型的优化和变更。

还有语句级别的统计信息。MySQL 自身具备语句级别统计信息,然而它的统计信息不够丰盛,因而在这个根底上咱们又减少了更多实用性的统计信息,比方 CPU 的应用工夫,加锁耗费的工夫等。

MySQL 里用了大量的 Mutex 来保障多线程之间的数据拜访,咱们加了对于 Mutex 加锁时耗费工夫的统计,不便对数据库热点的剖析。

这些统计信息提供了更充沛的数据根据,帮忙咱们做疾速的问题定位。

4. 稳定性:Buffer Pool 优化

在稳定性方面,咱们也做了大量的工作。首先是 Buffer Pool 的优化。

云上用户会有长期变配的需要。举个例子,在业务顶峰时,若心愿实例长期规格变大,过了顶峰之后再把规格降下来。MySQL 是反对线上的 resize,然而它的稳定性不够好。在做 Online resize 对性能的影响还是比拟大的。AliSQL 针对这个做了优化后,能够看到下图蓝色线条是动静变配的稳定曲线,稳定性好很多。

5. 稳定性:Concurrency Control 并发管制

用户经常会碰到几个 SQL 过去一下子就把实例的 CPU 打满的状况,或者是内存耗光等相似的状况。Concurrency Control 并发管制这个性能,能够让用户依据理论应用状况,对 SQL 限度执行个数,以进步实例整体运行的稳定性。

6. 安全性:TDE 反对国密 SM4

企业级用户对于安全性的要求越来越高,对于各种各样的加密、明码强度、生命周期等要求也越来越多。AliSQL 在平安这块做了更全面的反对,比方对于加密来讲,除了反对 TDE 这种 AES 的加密算法,还反对国密加密算法 SM4,对于有涉密要求的用户能够用 SM4 的加密算法来保证数据的安全性。

7. 安全性:Recycle Bin 避免误删除

当用户在做删除表或是 Truncate 表的时候,应用这个回收站性能,并不会把数据文件间接删除掉,而是会把这些表放到一个回收站里,这样就防止了用户在误删之后数据失落的危险,误删除后还能通过回收站把删除的数据疾速找回。

8. 安全性:Flashback Query

不仅是表级的误删除,当咱们对某一些数据更新的范畴谬误了之后,应用 Flashback 机制,能够复原到更新前的历史版本。同时,用户还能够自定义查问某个工夫戳的某个数据。

所以 Flashback Query 对误操作删除复原或是回档需要是很无效的办法。

9. 高性能:Binlog In Redo

比照原生 MySQL,AliSQL 的性能晋升很多。首先介绍的是 Binlog In Redo 性能。家喻户晓,在 MySQL 外面,事务提交的时候须要长久化两次,因为要执行两阶段的事务提交过程。这外面做了一个改良,即能够把 Binlog 写到 Redo 外面,这样的话就只须要长久化一次 Redolog,Binlog 能够异步刷盘。

通过这种形式,用户事务在提交的时候就只须要一次刷盘动作,因而时延会升高,吞吐量会增大。

上图是基于两个 Binlog in Redo 版本的测试后果。通过左侧第二个版本的数据,咱们发现性能会进步很多。对于 Update non index 来讲,能够有大略 38% 的性能晋升。对于 write only 来讲,也能够达到 25% 的性能晋升。

10. 高性能:Fast Query Cache

AliSQL 针对 Query Cache 在并发管制、内存治理和缓存机制等等做了大量的优化。

优化之后,它的性能晋升非常明显。在 point select 的场景下,性能晋升甚至能够达到 100% 以上。通过测试发现,在 rewrite 模式命中率比拟低的状况下,简直没有任何性能损失。所以用户在读比拟多的场景就能够把 Query Cache 关上,能够保持稳定高效的状态。

11. 高性能:DDL Optimization

围绕 DDL 咱们做了大量优化。

用户在应用 DDL 的时候会发现,如果表特地大须要做 rebuild 或更新数据等操作的时候,效率非常低。次要是因为 DDL 利用 Buffer Pool 的模型是效率低下的模型。优化之后,对于 rebuild 表的这种操作效率会高很多,对于其余 SQL 语句的影响也会升高很多。

下图是针对 Create Index 和 Optimize Table 的测试,能够看到优化之后,操作都会有 10 倍以上的性能晋升。

三、XA Crash Safe 介绍

1. XA Crash Safe 背景

抛开 XA Crash Safe 自身,MySQL 自身也有 Crash Safe 机制。为什么会须要这样的机制呢,因为在 MySQL 里,同时包含 Binlog 和数据两个局部,能够了解为存了两份截然不同的数据。为了保障这两份数据的一致性,MySQL Crash Safe 实现了两阶段提交机制。为了保障 Binlog 和数据的一致性,任何用户的事务都会被转化成为两阶段的事务,首先就是进行 prepare,而后再写 Binlog 并长久化,最初做事务的提交。所以在这两个阶段的提交过程中,Prepare、刷 Redo、写 Binlog 和刷 Binlog 的执行程序是放弃不变的。

如何保障 Crash Safe 呢?这要看它复原的处理过程。在理论的事务执行过程中,只有是 Binlog 有这个事务,肯定是 Prepare 的状态。那么利用这个准则,在 MySQL Crash 重启的时候,它会取出所有曾经 prepare 的事务,把它们的 XID 取出来,扫描最初一个 Binlog 文件,而后确认 XID 所对应的事务是否曾经存储到 Binlog 里了。如果曾经存储过了,就间接提交即可;如果还没有存储,就回滚掉。通过这个 Crash Recovery 机制后,Binlog 里的数据就和引擎外面的数据保持一致了。

对于普通用户事务能够用两阶段来保障 Crash Safe,那么对于用户的 XA 事务怎么解决呢?

在 Binlog 里会把这个事务分为独立的两局部,当用户执行 XA Prepare 的时候,会写 Binlog 文件,而后把这个 Prepare 状态执行到引擎里,这是齐全独立的。用户在 XA Commit 里,能够在任何工夫执行,当用户在执行 XA Commit 之后会被再记录一次 Binlog,所以这两者是齐全脱离的。

对于一般的用户事务,执行过程只记录一次 Binlog,而且整个事务是一个根本的单元存在 Binlog 中的;对于 XA 事务,这就是离开的。而且它整个过程是先写 Binlog,而后才去把状态长久化到引擎中,做引擎的 prepare。对于 MySQL 来讲,不能保障内部 XA 事务数据和 Binlog 的一致性。

也就是说当写完 Binlog,还没有在引擎中执行 prepare 和 commit,这个时候就 Crash 了,那么它起来之后就变成,Binlog 里有事务记录,而在引擎里却失落了,兴许只以 prepare 的状态停留在那里,这就没有被提交。

2. XA Crash Safe:基于 MySQL 5.7 的修复

1)调整执行程序

为了更好的反对分布式数据库系统,在 MySQL 5.7 的时候,阿里就做过对于 XA Crash Safe 的修复。这个修复是把执行程序做了颠倒,即先执行引擎的 Prepare,再写 Binlog,这样它就跟一般事务的过程一样了。在 Prepare 之后做 Crash,如果用户的 XA 事务做了 Prepare 之后没有记 Binlog,那么数据就会被回滚掉。然而因为 XA 事务跟一般事务不太一样,须要更多解决来反对回滚,而且它也不是一个欠缺的计划。因为用户具备多样性,比方用户执行了一个事务然而并没有记 Binlog,这个时候就没法辨别是否记录了 Binlog。另外,XA 事务的 Prepare 和 Commit 是离开的,当用户将 Prepare 事务记录到很久以前的 Binlog 里了,也不能辨别用户是否记录了 Binlog。

这种状况下就须要一个解决方案,即在做 Binlog rotation 时候,要把所有 Prepare 事务的 XID 记录到 Binlog 中。这样咱们就能够通过最初一个 Binlog 去理解所有 Prepare 状态的 XID,而后就能够通过 Rollback 的形式放弃 Binlog 和数据的一致性。

2)调整 Recovery 逻辑

Commit 执行了另外一种逻辑,即先执行 Binlog,在执行后发现事务是 Prepare 状态,且在 Binlog 中记录了 Commit 或 Rollback,那么执行 Commit 或 Rollback。

这就是 MySQL 5.7 上 XA Crash Safe 的修复的过程。

3. XA Crash Safe:MySQL 8.0 Gtid 和事务的一致性

MySQL 8.0 采纳了另外一种办法。介绍这个办法之前,首先介绍下 MySQL 8.0 Gtid 和事务的一致性。在 MySQL8.0.17 的时候,引入克隆性能,这个性能能够把 Gtid 记到事务的 undo 里。记到 Undo 里的过程也很简略,在 Prepare 的时候还是先记 Binlog,而后引擎里做事务 Prepare 的时候,去监测这个事务是否有 Gtid。如果有,在批改事务状态时会连通 Gtid 一起写到 Undo 里。如果 Crash 之后,Prepare 丢了,那么 Gtid 肯定也是不存在的,反之亦然。在 Commit 的时候也同理。这样做,克隆的时候用户应用起来就会非常简单。

然而 Rollback 是个特例,尤其是对于 XA 事务来说。Rollback 也会记录一个 Gtid。Rollback 在引擎里的做法是,把事务状态改成 active 之后就会天然回滚,所以在 active 的时候它也会记一个 Gtid,所以 XA Rollback 会记录 Binlog 也会产生 Gtid。整个操作也是原子的。

Gtid 最终会长久化到 Gtid_executed 表里。之所以要做汇总是因为 Undo 自身须要 Purge,否则会越来越大,而且检索效率也非常低。所以尽管在 Prepare 后会放进 Undo 里,然而实际上最初都会汇总到 Gti_executed 表中,而后会有一个独自的 Gtid Flush 的线程,它会周期性的把 Gtid list 里的 Gtid 写到 Gtid_executd 表中。写到表后,只须要继续化整个表后,undo 就能够丢掉了,这样始终会有一个残缺的 Gtid 汇合。

对于内部 XA 事务会记录两个 Gtid,一个是 Prepare 的时候,一个是 Commit 的时候。最后实现这个性能的时候,只会记录一个 Gtid,也就是说在 commit 的时候会把 prepare 的给笼罩了。这就要求,在 Commit 之前须要把 Prepare 的 Gtid 长久化到 Gtid executed 表里,效率非常低。起初官网优化成将两个 Gtid 别离存在两个地位,这就大大提高了效率。

通过以上的优化之后,咱们能够看到 Gtid 和事务数据之间的关系,是 Gtid Executed 表中的 Gtid 代表了 InnoDB 中曾经执行了的事务的 Gtid。这两者之间是原子对应的关系。

通过这样的对应关系,咱们能够在系统启动的时候做 Apply Binlog 这样的操作,来保障内部 XA 事务的 Crash Safe。

依据 Gtid Executed 表中的 Gtid 就能够晓得哪些事务在引擎里存在,而后通重放 Binlog 里的事务将引擎里的数据补齐。通过这样的形式,不须要批改过增加 Binlog Event,原来的 recover 过程也不须要变动。只须要在 recover 之后,查看 Gtid Executed 的表,而后比照 Binlog。将短少的事务从新 Apply 一下就能够了,这样就能够保障 XA 事务的 Crash Safe。

原文链接
本文为阿里云原创内容,未经容许不得转载。

退出移动版