开发者学堂课程【MySQL 实战进阶:MySQL 分支-AliSQLSQL 的性能优化实战】学习笔记,与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/83/detail/1311
MySQL 分支-AliSQLSQL 的性能优化实战
内容介绍:
一、内核研发
二、内核特性
三、版本对齐
四、全网功能
五、内核-实用性
六、内核-高性能
七、内核-稳定性
八、内核-安全性
一、内核研发(从需求和技术出发对 AliSQL 内核提更高要求)
1、本课程讲解过去一年中在 AliSQL 中核心的技术,这些技术的出发点、背景以及效果。因为内核是非常重要的,所以投了很大的力量做内核研发。在使用云的过程中,可能会有决策时间、架构的时间和数据迁移的时间,这些东西都做完之后,稳定的数据库内核是最重要的,因为它会伴随最长的时间。花大量时间提升内核是非常正确的事情。
2、阿里做内核研发,对自己提了两点要求。第一点是从用户和客户的角度,希望加一些非常实用的功能。
(1)比如说 outline 功能,临时修改一个 sql 的计划,把他从错误的计划修改成正确的计划;做 flashback 功能,在有数据、有误操作的时候可以快速的把误操作之前的数据找回,这些功能非常实用,是很重要的一点。
(2)提高性能,希望有更高的 QPS 或更低的 rt,这对应用非常重要。
(3)稳定性,提高高并发效果的稳定性,更快的问题分析能力。
(4)提升安全性,对于通信,对于应用到数据库链接进行加密、数据存储进行加密,还可以防止随意删表,对删表整个流程做特殊的权限控制。还研发了回收站,有删除操作的时候,先把要删除的东西移到回收站,而不是真正的删除,对回收站进行特别的权限控制。在考虑研发内容的时候,是从这四个点出发,所有的需求都会到这四类中。
3、另外一点是技术的要求。
(1)AliSQL 是从秒杀场景开始,秒杀是一个业务场景的需求,这是不够的。从云上用户的产品出发,做的基础要让所有的云用户收益。
(2)功能和技术必须注意通用性,不需要特殊的场景才能用,而是在所有场景下都可以使用。不需要用户调整,不需要修改 sql 或应用,自然而然的失效。
(3)不同的功能在不同的版本之间具有连续性,RDS 56/57/80 上行为一致,甚至在 MySQL 9.0中也有行为一致。
(4)技术的领先性或叫独创性,希望这些技术在各个版本中都没有,是阿里想出来的独创性的需求。
二、内核特性
1、在整个阿里云里,对所有的基础进行了分类。实用性有四个功能,分别是动态线程池、Flash back 查询、SQL Outline、自动热点排队。
2、高性能的四个功能,分别是索引锁优化、Binlog In Redo、高效查询缓存、多块读。
3、在稳定性方面有四块改进,分别是快速 DDL、性能监控插件、BP 动态伸缩、页面淘汰优化。
4、安全性方面增加了对国密(SM4)支持、防删表保护,DDL 回收站。
三、版本对齐
下图是功能在每个版本上的情况。
研发从8.0开始,然后到5.7,最后到5.6上。有两个功能不会在5.6上做,一个是 SQL Outline,因为这依赖 hiet 技术。在5.6中没有 hint技术,所以不会做。还有一个是 BP 的动态伸缩,在5.6原生框架中不支持,其他的功能都是可以对齐的,说明在阿里上的所有功能,都有非常好的延伸性。
四、全网功能
有些功能达到了非常多的使用,把它称为全网功能。全网功能有四个,分别是动态线程池、索引锁优化、快速 DDL、性能监控插件。全网功能要求有数十万实例开启使用,运行一年之久没有问题。接下来的目标是让所有功能都成为全网功能。
五、内核-实用性
1、实用性的功能主要有四个,第一个是动态线程池。这个功能非常重要,对数据库的使用越来越深入,数据量也越来越大,应用到数据链接数越来越高。一般情况下,链接数变大的时候,线程会下降。看下图
灰色的线横坐标是数据库的链接数,纵坐标是 QPS。到一定的巅峰之后,会开始下降,但是有动态线程池技术以后,链接数保持平衡。线程池有四个非常重要的功能,分别是独家默认开启、节约内存、节约 CPU、节约线程资源。因为它是用一个线程服务多个请求,可以解决高并发的问题。如果一下来非常大、非常多的请求,前面讲的秒杀场景,线程池对秒杀很有帮助,假如一下来三千,五千甚至一万个请求,线程池可以保证它的性能不下降。
2、让 RDS 支持更高的链接数,用了线程池以后,最高的链接数已经达到了50万。第三个是高性能,看上图曲线。在一千个链接以后,差异越来越明显,甚至到八千个链接,原来的 sql 已经用不了了,但是在动态线程池下,可以继续使用。线程池在三个版本上全部默认开启,并且运行超过一年之久,没有任何问题。
3、使用线程池后的收益
左边的图和右边的图是开启线程池和不开启线程池的区别。第一列有Load,没有线程池的时候 Load 很高,计算方式跟多少线程有关系,比较process CPU 的使用,还有 CPU 的利用率和内存。没有使用线程池的时候,内存是十个GB,使用线程池以后,Load 降到3.98,内存节约了200 MB,有没有这200MB 可能会决定实例有没有 OM。下面黑色部分是真实实例的性能数据,这是一个备库,它的数据库链接数有15400个链接,在动态线程池下,后段只需要127个线程,就可以提供非常平稳的服务。
4、Flash back 查询
很多时候可能会遇到这样的场景,比如有些表不小心做了误操作,Update 语句的 where 条件写错了,或者根本没有指定 where条件,或者是delete 语句,这些语句是非常有伤害性的。原来需要解析 binlog 进行数据恢复,现在SQL语句加了 TIMESTAMP 语法,可以回到过去的时间点,把误操作之前的数据查出,用这些数据进行恢复。
5、SQL Outline
SQL 计划很多时候可能发生变化,做了增减索引、统计信息、版本升级、参数变更,跟优化器相关的参数。有时候数据本身的变化,比如数据分布的变化,还有优化器的缺陷,或者是程序很难修改,改起来很复杂,或者是改完之后上线步骤很复杂,SQL 走错的情况很紧急,这个时候可以用 outline 修改。下图是真实遇到过的 SQL
这个 SQL join 顺序出错,导致性能很差。用outline 基础之后,只需要调用存储过程,黄色字体是调用 outline 设置。SQL 设置一个hint,使 sql 的执行计划变准确,这是给 EDA、业务或者应用开发提供一个非常好的应急手段。
6、自动热点排队
这是对 AliSQL 秒杀技术的升级,秒杀技术要求对同样的更新在事务上排队,不让它进入事务层。同样的更新进入到事务隐藏层的时候,会造成事务引擎识索检测的成本非常高。原来的版本加了 hint,告诉这台 SQL 要以什么样的 ID 顺序进行排序,这个 ID 排序通常涉及主键。通过语法分析,可以把这一块透明化,不用去更改 SQL,可以自动识别编写语句走的是主键或者是 uka 索引。走的是主键或者是 uka 索引表示单行更新,可以自动把 wei 条件值取出,做 hash,分配一个队列。
六、内核-高性能
在性能方面 AliSQL 的改进,也分为四块。
1、索引锁优化
数据库数据进行插入的时候,可能会导致索引的分列,在 MySQL 里索引的分裂操作是非常重的。这方面做了优化之后,极大的减少了索引分裂的概率和它的深度,深度指的是防止从叶开始分到根,导致层层传递的裂变,把这种情况最大可能的消除掉。好处是带来50% TPCC 性能的提升,下图是一个测试。
在实验室里,会把 MySQL TPCC 的值压缩到39万,左边是真实运行数据的截图,这表明压缩数据是真实的。右边是顶查的测试,索引怕对顶查也有帮助,可以压到100万 QPS。
2、Binlog In Redo
这个技术可以提升 commit 的效率,MySQL 为了保证数据的一致性,要求 redolog 跟 binlog 同时刷出去,就是非常出名的 redolog 跟 binlog 两阶段提交机制。一个事务开始之后,到提交阶段的时候,首先会发 redolog,会涉及到一次IO;接下来会刷一次 binlog,又涉及到 IO,然后才是真正的锁示范。在使用存储或者使用云盘的时候,可能会让性能变得不理想。研发 Binlog In Redo 之后,把 binlog 先写在 redo 里,刷一次 redo 之后就可以保证 binlog 不会丢失,真正消耗的IO 只有一次。
左边的流程图,只在一次 io 之后,就可以把整个事务锁到示范,就是提高了 commit 的响应速度,更早的释放了锁的资源。带来的好处是时隐变短,事务提交的性能提升了。在测试中,性能可以提升 25% 左右,这是对任何场景都通用的。