开发者学堂课程【MySQL 实战进阶:MySQL 分支-AliSQL 的性能优化实战】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/852/detail/14065
MySQL 分支-AliSQL 的性能优化实战
内容介绍:
一、内核研发
二、内核特性
三、版本对齐
四、全网功能
一、内核研发
讲解 RDS、AliSQL 做的一些核心技术,这些技术的出发点背景以及最后的效果,投了很大的力量在做内核研发,因为内核是非常重要的,在使用云的过程中可能会有决策时间、价格时间、做数据迁移的时间,做完之后发现稳定的数据库内核是最重要的,它会伴随你最长的时间,所以花大量的时间来提升内核是非常准确的事情,怎样来做数据库内核研发,提了两点要求。
第一个是从用户客户的角度加一些非常实用的功能,比如修复 plan 的功能,可以临时去修改一个 SQL 的执行计划,把它从错误的计划变成正确的执行计划,还有一个就是 flash back的功能,在做数据误操作的时候,可以快速的把误操作之前的数据找回来,这个功能非常实用,是非常重要的一点;
第二个需要提高性能,有更高的 QPS 和更低的 RT,这些应用也非常重要;
第三个是稳定性,提升高并发下的稳定性和更快的问题分析能力;
第四个是提升安全性,比如对通信、应用数据库连接进行加密,对数据的存储进行加密,还可以防治随意删表,比如对删表整个流程走特殊的权限控制,还研发了回收站里有删除操作,要删除的东西移到回收站不是真正的删除,对回收站进行特别的权限控制。在考虑研发内容的时候从这四个点出发,所有的需求归到这四类。
另外一个是技术的要求,MySQL 是从秒杀场景开始的,认为秒杀可能是电商一个业务场景需求是不够的,从云上用户的场景出发,也就是做的技术能够让所有的用户受益,
第二个受功能和技术必须具备通用性,这个通用性指的是不需要在特殊的场景下才能用,而是所有的场景都可以用,不需要用户来调整什么,不需要去修改 SQL 或者修改应用,它自然而然地在后面生效。
第三点,要求功能在不同的版本之间具有连续性,比如要求做的技术在 RDS 上有,在56、57、58、80上也有,甚至在 MySQL 9.0里面也会有。第四个就是在技术的领先性,或者叫独创性,这些技术在各个版本里都没有,是想到的一些独到性的需求放进去。
二、内核特性
按照前面的分类,实用性有四个功能:动态线程池技术、Flashback、SQL Outine、自动的热点排队。
性能也有四点:索引索优化来提升性能、Binlog In Redio、MySQL 查询缓存、多快读技术。
稳定性方面有四块改进:快速 DDL、性能监控插件、BP 动态伸缩、页面淘汰优化。在安全性上面,增加了对国密(SM4)支持,并且有防删表保护的功能和 DDL 回收站。
三、版本对齐
下面来分别介绍这些功能在每个版本的情况,研发首先从 RDS 8.0开始做的,做到 RDS 5.7,最后在 RDS 5.6上面,这里只有两个功能在5.6上是不会去做的,一个 SQL Outine,因为这个依赖于 hint 技术,在5.6原生框架里没有 hint 技术,还有一个是 BP 动态伸缩,在5.6的原生框架里也没有支持这块,其他的功能都是可以对齐的,说明在2020年设下的所有的这些功能都是非常好的一个延续性。
四、全网功能
这里面有几个功能已经达到了非常多的实例素材用,可以把它称为全网功能。全网功能有四个:动态线程池、索引锁优化、快速 DDL、性能监控插件。这些全网功能要有数十万实例开启再使用,而且是运行一年之久没有问题,接下来的目标,所有的功能都成为这样的全网功能。
1、实用性
(1)动态线程池
实用性的功能主要有四个,第一个是动态线程池,这个功能非常重要,现在对数据库的使用都是越来越深入的,数据量也越来越大,应用到数据库连接数越来越高,一般情况下当连接数变大的时候,connection 会下降。
图上有条灰色的线,灰色线的横坐标是数据库的连接数,纵坐标是 accu ps,在一般情况下,到一定的变化以后就开始下降,但有动态线程池技术后线是可以平的。
线程池有四个非常重要的功能:节约内存、节约 CPU、节约线程资源。用一个超性的线程来服务多个请求可以解决高并发的问题,比如一下来了个非常大且非常多的请求,比如前面讲的秒杀场景,线程池对秒杀也很有帮助,比如一下来3000个请求或者4000、5000、10000个请求,那么线程池可以保证它的性能不下降。
第二个可以让 RDS 支持更高的连接数,用了线程池技术以后,把最高的连接数在技术上已经达到了50万,第三个是高性能,这个曲线再上1000个连接以后差距会越来越明显,甚至到8000个连接有可能原来的 CP 跑不动,但是在动态线程池下面都非常好。还有一个是线程池在3个大版本上全部已经开启,并且是默认开启,运行超过一年没有任何问题,说明这是非常成熟的线程池。
线程池收益:
如上面左右对照图所示,是开启线程池和不开启线程池的区别,第一列有个 Load ,这列是没有线程池的时候 Load 很高,因为 Load 的计算方式跟有多少线程堆在那里有关系。
还可以比较 CPU 的使用、CPU 利用率、内存,没有使用线程池的时候,内存是 4GB ,但使用了线程池后 Load 降到3.98,内存差了200兆,这200兆可能决定着实例会不会被 ON。下面黑色的图是一个真实实例的性能数据,这是一个备库,它的数据库连接数有15400个连接,在动态性质下面后端只需要127个线程可以提供一个非常平稳的服务。
(2)Flashback 查询
遇到一些场景比如一些表不小心做了误操作,比如 Update 语句的 Where 条件写错,或者根本没有指定条件,或者 Delete 语句,这些语句是非常具有伤害性的,遇到这种的时候,原来需要去解析数据恢复,现在在 SQL 语句里加 as of stamp 语法,就可以回到过去的时间,并把这些误操作之前的数据查出来,然后用这些数据进行恢复,这是个非常实用的一个基础。
(3)SQL Outline
SQL 在很多时候可能会发生变化,当做了增加索引或者删除索引,做的统计信息的重新收集或者数据库版本的升级,比如5.6升到5.7,或者调了一些参数,比如优化相关的参数,还有的时候可能数据本身的变化,比如数据分布的变化,还有优化器的缺陷,或者就是程序,其实很难改程序源代码,改起来很复杂,或者改完了之后不止很复杂,但是 SQL 走错的这个情况会很紧急,这时可以用 Outine 修改,下边是一个真实遇到过的 SQL,
这里表明都已经处理掉了,这个 SQL 就是专业顺序出错导致性能很差,在有 Outine 技术后,只需要调用的存储过程,右下角有调用 Outine 设置,就是给 SQL 设置一个hint,SQL 的执行计划就准确了,所以这是给 DBA 或者给业务或者给应用开发提供非常好的一个临时的应急手段。
(4)自动热点排队
MySQL 秒杀技术的升级要求对同样的更新及在设备上排队来不让其进入事务层,因为同样的更新进入到事务层的时候会造成事务引擎检测的成本非常高,第一版本加的 hint,就是告诉 SQL 要用什么样的 ID 进行排序,ID 排序通常设置组件,通过语法分析,可以把这一步透明化,就是不用更改 SQL 了,自动识别编辑语句是走的是组件或者 ukey 索引,如果是走的组件或者 ukey 表示当场更新,可以自动把 where 值取出来做分析,之后来分配一个队列,原来需要改接口改应用,现在不需要了。
2、高性能
(1)索引锁的优化
数据库数据件插入的时候,可能会导致索引的分裂,MySQL 索引的分裂操作非常重,在做了优化后极大的减少了索引分裂的概率和深度,深度指防止从叶子尖一直分到根,就是全部导致层层传递上去的裂变,把这个情况给最大可能地消除掉,会带来50%的 TPC 性能的提升。有一个测试,在实验室里把 TPCC 的值压缩到39万,上面是这个正式运行的一个截图,表明压缩数据是真实的,右边是检查的测试,这个检查可以压到100万 QPS。
(2)Binlog In Redo
这个技术可以提升 commit 的效率,MySQL 为了保证数据的一致性,要求 Redo 跟 Binlog 同时刷出去,就是两个阶段提交机制,当一个数开始了后,到提交阶段的时候首先会刷出 Redolog,这个涉及 IO,接下来会刷起 Binlog 又涉及 L,然后才是真正的释放。在使用存储或者云盘的时候,可能会让性能变得不那么理想,研发了 Binlog In Redo 之后,把 Binlog 先写在 Redo 里,只要刷一次 Redo之后,后面可以保证 Binlog 不会丢失了,真正需要 R 只有一次了,最左边的流程图是提高了响应速度,也更早地释放的锁的资源,好处是事务性能提升,测试中,性能可以提升25%左右,对任何场景都通用。
(3)高效查询缓存
MySQL 本身有查询缓存,在8.0计算做的社区能把查询缓存去掉,左边这个图,如果没有缓存,一条数据库语句进来要经过解析,要检查权限,要优化对数据库进行分析,来得出最好的执行计划等真正的执行,执行过程中涉及的事务引擎可能会访问存在磁盘上的数据,经过查询缓存能够命中的时候,这个过程就非常简单。查询缓存是对结构体的一个缓存,称之为 concend reread cation,跟四五机制结合在一起,从缓存查出来的数据也是满足事务的隔离级别的,在4G、8G 的机器上测试,发现可以有100%的提升,这里测试了三个配置,第一个是查询缓存关闭的情况下,这是原生的把查询系统关闭,关闭的时候,跟最高的比,橙色是 MySQL 原来的 Recation,设计比较陈旧,所以现在的印记下起到了相反的作用,这也是把它去掉的原因,但解决最关键的问题,设计了一个非常独到性的机制,一个缓存的维护,更新维护机制,能够达到100%的性能提升,这些开启了参数在控制台可以修改,可以直接启用。
(4)多块读
通过非常深入的代码阅读和分析在处理 L 的时候,基本上都是一个块一个块去读,比如查询一张大表发现要这快读完了处理一下,然后再读下一块,这个过程是非常浪费时间的。第一个块的时候,后面连续的块也读进来,把这个称为多块读,这里也做了一个测试,左图是对一个10G 的表采用原来的机制,右边使用了多块读的技术,对大的查询,比如 select 新发了一个表,没有条件,查询大量的数据的时候非常有效。
3、稳定性
(1)快速 DDL
过去用户需求在业务有点高的时候做 DDL,发现在 Mac 的办法破例,数据块是很多表或者索引的,数据是混合存放的,当要做 DDL 的时候,要把整个扫描一遍来看看,这个扫描的效率是非常低的,基本上所有的 DDL 所有的对表要进行重组的,加入一个新的一个导航的机制,可以快速的定位到哪些 export 的事,操作的这个对象,这样扫描效率大大提升。
测试场景开启压测,128张表每张表示200万的数据,在压制的过程中,做 export table 操作,这个操作会把 export 扫描一遍,如果没有快速 DDL 特性,需要80.51秒,有快速 DDL 特性后,只花了0.34秒,这个特性也是全部默认开启,是非常流行的一个全网功能。
(2)性能监控插件
数据库会经常遇到一些性能问题需要去分析,这时候一个实时的性能数据就非常重要,一般执行成本非常高,很难保证每秒钟都有新的数据输出,所以把性能数据的收集做在内核里。
从任何角度可以直接读取内存位置,把数据写到文件里,这样可以做到每秒钟一个数据。不管负载怎样,基本上非常准时。数据有两种存储方式,第一个存在格式化文本文件里面,采用三个文件,每个文件到100兆就切换,可以对过去的性能信息进行回溯。
另外,还提供一个内存的表,这个表里查询的时长可以自己定义,可以直接来访问这些表,比如右上角曲线,对这个实例的 select、insert、update、leader 查询,用曲线画出来,这个数据也可以访问,大概在分析性能问题的时候,可以跟基于同一份数据来进行交流,这样会加快问题分析的速度。
(3)BP 动态伸缩
对 BP 进行调解的时候扩大没有问题,但是如果缩小会有很大问题,为什么要调 BP,内存使用分成两块,一块是数据内存,数据为了加速访问放在 BP 里的,还有一块是程序,每一个规划都会用内存,当连接数据多的时候,其实 BP 可能要调小一点,感觉比较小的时候,BP 可以调大一点,这个动态的 BP 机制能够更好地利用到内存,所以需要解决 BP 动态缩小的问题。这是测试,绿色的线是 MySQL 在做 BP 缩小的过程中抖动非常厉害。
对这个问题进行深入的分析,进行技术突破,再测的时候看蓝色的线,虽然也有抖动,但是抖动的幅度就少很多,最坏的情况就跌20%。如果 BP 动态伸缩的技术,加上业务相对不太高的一个时间段,可以做到完全没有影响。
(4)页面淘汰优化
MySQL 在内存比较紧张的时候很容易引单页淘汰,读一个数据块进来在内存里找不到一个空的数据页的时候,要去淘汰一个数据页,这时会一页一页的去淘汰,效率非常低。
这里做了一个机制改进,把淘汰一页的概率降到最低,就是提升了淘汰页面的效率,没有当页淘汰,最少是比如采用16页的淘汰,这样的性能得到很好的提升,这里有四条线是两种场景。
上面两条线是测试没有打开范围查询,高的线是页面淘汰优化之后的线,它比没有优化之前提升了20%,下面那条线是打开了范围查询的情况下,因为有些 SQL 比较复杂,会查询比较多的记录,所以它的 KPS 低一点,发现提升幅度在15%-20%。
数据库数据大于内存是一种常态,这块的优化其实是非常大的提升,可以用更低的资源配置得到更高的 cpu,这是非常节约成本的。
4、安全性
(1)国密(SM4)支持
数据安全的风险很大,国家也对加密算法有要求,有自己的标准,所以增加了对 SM4算法的支持,在 TDE 功能里面可以选择使用 SM4算法进行加密。
(2)防删表的功能
把上次表的权限收起来,比如收到某个用户的指定账号或者要通过管控平台才能够进行删除数据,或者要求删除操作只有在本地连接下才能做,通过这种不同的级别可以起到不同的安全效果。
从保护内容、保护级别上来讲有两类,第一类是数据类,包括 Drop Table、Truncate Table、Alter Table Drop、Partition、Alter Table Truncate、Paritition、Alter Table Exchange、Partition、Drop Tablespace,还有一些是对存储过程视图,这些定义的保护,享用这个级别的时候可以禁止你去删除视图的定义,禁止删除存储过程,禁止删除触发器,甚至禁止删除别人的 logo,看到这个丰富多彩的结合可以起到很好的反数据保护的作用,可以确保数据库的运行安全。
(3)DDL 回收站
从左边来看,在阿里 SQL 8.0里面,数据库里有一个 recycle bin 保留的数据库名字,意思就是回收站。
开启了回收站的功能后,删除的时候不是直接把这个表删掉,而是把这些表先移到回收站里,后面还可以找回来,对回收站的权限做了特别的控制,需要有特别的权限才能够去真正的破解这个表。
看右边,这一般是没有权限的,需要更高的权限才可以破解,通过一个两级的机制可以有效的防止表被删掉,或者不想开启前面的防删表策略,可以开启回收站,当发生误操作的时候,可以从回收站快速的找回这个数据。