Non-FPW开发实战

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 在阿里云开源的趋势下,如何做到FPW的开发。

分享人:吕海波(VAGE)   杭州美创科技内核专家

正文:本文从八方面介绍了FPW的开发实例。


一、为什么要对FPW动手:性能测试


1)性能影响对比,PostgreSQL Full Page Writes性能影响:


image.png

先对比下性能,左侧是打开FPW,右边是关掉FPW,这个跟IO是强相关的,如果IO很快速,FPW的影响就越小,如果使用的是土豪级NVM1设备,FPW的影响可能就没有了,甚至观察不到有任何的影响。平均FPW性能的影响可以达到百分之值30以上。


2)性能影响对比,MySQL Double Write性能影响


image.png

对比下MySQL,FPW的功能主要针对在页分裂或者不分写,页破碎等,对应到MySQL里面针对页分裂不分写的特性是Double Right双写。在同一台机器上测试一边打开双写,另一边关闭双写,同一台机器上使用同样的压测软件的,可以看到MySQL双写对性能的影响是微乎其微的。


二、为什么要对FPW动手


image.png

PG的FPW影响也很巨大,所以对它动手可以最大程度提升性能,代码改动比较少,实现逻辑也很简单。


三、了解FPW


1)页裂


image.png

那要在对它动手之前,特性是针对页裂的,针对不分写或页破碎,数据库的页一般是4k的倍数,8k 、16k等,数据库下发一次写,可能操作系统前4k写成功后4k写失败,这就导致不分写或者页分裂,在对它动手之前要先了解一下赠分裂,了解它对数据库的影响,数据库是怎么解决的。

image.png


2)页裂的模拟


image.png

我们去制造一个页分裂,走两步看看数据库是怎么处理页分裂的,然后再对它动手。

制造一个叶分裂也简单,突然中断电源,内存里就页分裂,不分写、页分裂、破碎页等情况,这种方式可以实现但有点粗暴。直接中断电源不能针对某一个固定的页,比如想把某个页制造成页分裂是做不到的。如果脏页多又突然断电,这种情况可控性就比较差。如要去针对某个表、普通表、原数据表,针对某个固定的页去制造一个页分裂,可以拦截系统调用,再去修改传入OS内核参数拦截系统调用。比如在Linux里面这个systemtap就能做到,我之前有过关于这个systemtae的很多分享,就是用它去观察PG、,MySQL等,也比较简单。

 

3)从MySQL开始


image.png

主要思想是用它拦截IO,然后把IO的大小改一下,比如让操作系统写8k,把8k拦截后改成4k,就让前4k写成功,后4k不写,这就是页分裂。这种数据一致性让性能提升很诱人,但是做不好数据就不一致就没用了,那就没有任何意义了。

我们先从MySQL数据库开始,可以都比一遍,多借鉴各个主流数据库的经验,再决定如何对FPW动手。制作MySQL的页分裂,就要先去做IO函数,如果打开的话,它使用异步IO,如果关掉的话,使用同步IO,我们使用同步IO做测试,因为今天时间比较紧张,异步测试会比较复杂,讲起来又耗时多,但是总体思路是一样的。


4)从MySQL开始


image.png

因为要拦截系统,所以要先找到IO函数。这是测试表就不详细说了。

image.png

我让目标行MySQL的块是16k,让行呢处在靠下的位置,第三个4k的地方MySQL空间,它是从上往下使用的。我插入200行,以第200行作为目标,到时我去更新这个第200行。当我更新这个第200行的时候,MySQL更新这个4k外,第一个4k也会变,因为第一个4k前面管理性信息,这样第一个4k也变了,第三4k也变了。

image.png

我让目标行MySQL的块是16k,让行处在靠下的位置,第三个4k的地方。MySQL空间是从上往下使用的。我插入200行,以第200行作为目标。

image.png

到时我去更新这个第200行。当我更新这个第200行的时候,MySQL更新这个4k外,第一个4k也会变,因为第一个4k前面管理性信息,这样第一个4k也变了,第三4k也变了。

image.png

这是测试语句,是一条update更新第200行,中间还有个脚本,脚本上面是一个探针,探针就像数据库的触发器一样,先去做输出,输出是把函数的一些信息接过来,上图是输出的这个结果,那我做一个update,触发了MySQL的写操作,触发把内存改小一点,如果内存太大, update知道脏页要先修改一些参数。

image.png

 

image.png

制造了脏页后,让MySQL尽快去写这个页,在这儿就能看到输出的结果了,这个28就是写目标表的IO,这个文件号28十进制就是40。在目录下就能找到表对应的文件号,在这里就不详细说了。

image.png

它还写了0*b号文件,0*b号文件是第一次写18000的六个页,也是双写,待会儿我要让双写、四号文、日志log redo都成功,后面几个写有UNDO、系统表、28号写都失败。

image.png

观察过IO后,生成一个脚本进行破坏,就是对指定的进行破坏,让redo、双写都成功。因为双写失败了,还要靠再去恢复,看双写是如何恢复的。

image.png

这是最终运行效果。先运行脚本,再去执行update,执行完之后,IO被触发了,查询后发现MySQL已经宕机了,因为发现IO报错了,所以就宕库了,就启动不了,因为它检测到有页被写坏了。因为涉及到数据一致性的特性,我做过大量测试。

image.png

动手之前要做大量准备工作,如果这个制造的坏页,是对用户表的话大部分都能启动成功的,如果涉及到UNDO、系统表,用双写去恢复成功的概率那就很低了。

image.png

总体看双写不能对所有的页分裂和不分写发挥想象中的作用,它只能针对部分页分裂。如果出现这样的问题怎么办?就是做备份恢复,就能解决Partial Writes。对MySQL来说,就是you may have to recover from a backup,就是要靠备份恢复。


五、业内标杆,Oracle的页分裂解决方案


image.png

虽然说在国内Oracle的形势有点日落西山了,但是技术上仍然有它的先进性。下面观察Oracle,看它的页分裂的解决方式,跟MySQL步骤一样。首先找到IO的函数做拦截,Oracle的IO函数打开IO的时候是submit,跟MySQL是一样的。

image.png

准备测试数据的时候就简单了,建个表插一行就行,因为的空间是倒着来的,你插一行它就在第二个4k,然后你更新着Oracle第二个4k目标行,第一个4k也会改,因为块头有管理性信息,修改完目标行后,需要手动触发检查点。Oracle写是比较延迟的,PG也是一样。手动触发检查点,再触发它的写操作,再拦截系统调用,把8k改成前4k成功后4k失败。

image.png

再去看Oracle的处理过程,先观察Oracle的操作有哪些。

image.png

然后观察Oracle的结果,除了对我的目标表外,它还写了 UNDO等,我把这些都破坏掉变成坏页。

image.png

脚本是这样的,最主要就是中间这一行,把它改成改成1000,因为2000是16进制的,16进制2000就892是,把它变成1000,只要一改Oracle,IO就会报错了。MySQL脚本还比较复杂,最终要让IO报错,不能让IO成功。

image.png

先让脚本跑起来, update是成功的,cmmit也是成功的,执行检查点时报错了,因为这个写是Oracle的核心进程,核心进程出错之后它就直接down了。

image.png

Down后看如何去恢复。启动到这个地方,报错没有启动成功。

image.png

从日志里可以看到很多信息,在Oracle的告警日志里,发现数据库上次是异常宕机了。

image.png

找到了一个恢复点,从日志redo的地方去恢复,叫7112号redo文件的1736号块,它要从这个地方去恢复。

image.png

PG里面也有类似的东西,它如何恢复起始点呢?对所有数据库来说,只要保证数据一致性,比如不能因为断电数据就完了,只要能做到这一点的数据库都要有redo,redo对它来说是日志流。Record跟脏块是一一对应的,而且Record的顺序就代表了脏块的顺序, Record1:在Record2前,那Record1对应的脏块比Record2对应的脏块更早变脏。Redo从某种意义上来说相当于一种时间,这所有数据库都差不多,MySQL和Oracle都以redo为准。

image.png

检查点位置对开发很有意义的,它定期去执行检查点,检查点就是写脏块,数据库都有这样类似的机制,比如说这次检查点开始时写了四个脏块,还剩四个脏块,其中四个块已经落盘了,还有四个没有落盘。

image.png

第五脏块在redo里对应的位置就叫检查点位置,这个检查点位置就是我们在告警日志里面看到的恢复的起始点,7112号块的1736,因为已经落盘成功了,在这个位置之前的脏块都是不需要恢复的。

image.png

它落盘成功后才会把检查点位置寄到控制文件里面,Oracle和PG都有这样的机制,也是在检查点完成后把位置记到控制文件里面,这个位置之前的脏块儿都已经落盘成功了,恢复时就从这个地方开始往后去redo恢复就可以了。

image.png

Oracle检测到这个日这个检查点位置之后,检测到有74k的redo,74k的redo对应24个块需要恢复。

image.png

在恢复的时候没恢复成功,数据库不对坏页修复。

image.png

页坏了后有redo,页坏的可能性千奇百怪,数据库不会以有涯随无涯,它要在以前完好的数据的基础上做恢复。MySQL的双写和PG的FPW都是需要时不时的做个备份,把完好的一致的数据做个备份,以备将来在这个基础上做恢复,数据库不去做修复只去做恢复。

image.png

Oracle遇到坏页、页分裂、不分写、页破碎,它是如何做的。Oracle依赖检查,只要能检查出来页有问题就可以了,检查出来让DBA做恢复,你不恢复成功数据库我不启动,如果数据库启动了,就代表你已经恢复成功了,它的数据是一致的。

为了尽快完成恢复,它提供了快恢复的功能,比如说32G的文件夹有8k坏了,MySQL怎么做呢?如果双写没有搞定,那把以前备份的文件就一个表一个文件把这个表给恢复过来, 32G数据全部来一遍,就会比较慢。

Oracle有块恢复功能,如果只有一个块或者部分块坏了,只需要恢复问题块,而不需要32G全部来一遍,这是Oracle应对页分裂的方式、检查和介质恢复。


六、PG如何处理页分裂


image.png

PG的测试过程,PG的IO函数pwrite,测试过程跟oracle差不多,PG机制跟Oracle机制是更类似一些,行也是倒着用,MySQL的行是正着来的。

image.png

所以我要插200行,把这个目标行撑到第二个或第三个4k,Oracle和PG是插入一行就行了,间隔表插一行在最末尾,在这个页的第二个4k,更新第二个4k,第一个4k也会变,也要手动触发检查点拦截系统调用,改8k为4k,让前4k写成功,再让IO报错。

 

image.png

在测试之前我先用一个简单的小脚本看一下。

image.png

它的写没有Oracle那么多,比MySQL的也少,没有UNDO,所以写会少一点,第一次这个写是针对WAL日志的,第二次写也是针对WAL日志的。

image.png

这些都让它成功,日志不成功没法做恢复。

image.png

第三次写是针对目标表的,要让四号文件写是失败的,其它的都是成功的。

image.png

上图是脚本。针对某个固定的进程,16045就是checkpoint的进程,让四号文件满足条件后才去破坏,最终这个条件也是为了让IO报错的,不能让io成功。前4k的IO是成功的,后4k是失败的。

image.png

上图是脚本。针对某个固定的进程,16045就是checkpoint的进程,让四号文件满足条件后才去破坏,最终这个条件也是为了让IO报错的,不能让io成功。前4k的IO是成功的,后4k是失败的。

update执行是成功的,commit也是成功的,执行checkpoint是失败的。

image.png

目标就是让它是失败的。这个数据库并没有宕掉,PG还是比较坚强的,如果把IO破坏之后MySQL就直接down了,Oracle也直接down了。

为了模拟,把所有的PG进程一起宕掉,就像页分裂是断电分裂,其实只kill第一个主进程也是可以的,kill多点保险点,这样就能看到日志里面有大量的IO报错,再重新启动的时候,PG找到了恢复的位置,这个恢复位置跟Oracle机制一样,这个位置就是检查点位置。

image.png

从日志的这个地方恢复成功后,数据库最后的启动过程也是成功的,连上后查我目标表,这个目标表数据查出来后,触发语句大写转小写。最终看到数据就是小写,页分裂问题就搞定了,它是以巨大的性能的代价解决了这个问题,,最终问题解决了,就是性能下降确实有点大。

image.png

这个页分裂是偶尔出现的一个问题,偶尔出现荡机,还不是当库,所以操作系统宕机和断电这种情况是极其偶尔出现的,为了一个极其偶尔出现的情况,引入性能损耗比较大的特性值得吗?


七、PG如何处理页分裂 --- 关闭FPW时的测试


image.png

对比各个主流的数据库后,我们要对FPW动手了,今天先讲第一步,刚才是把FPW打开时的测试,那把FPW关掉再来一遍,看下页分裂是什么情况。

image.png

整个测试过程是一模一样的,唯一区别就是把FPW关掉了,关掉后update是成功的,提交也是成功的,因为是隐含提交的。

image.png

Checkpoint也是失败的。

image.png

整个测试过程是一模一样的,唯一区别就是把FPW关掉了,关掉后update是成功的,提交也是成功的,因为是隐含提交,Checkpoint失败,

重启数据库时候发现这个数据没报错,就是因为前面把它改成小写了,但是这个地方可以看到是大写的。如果关掉了FPW后,数据可能是不一致的,但是这是在没有打开Checksum的情况,如果打开了通常还是会报错的。这样测试我做了很多遍,这个测试结果我还不确定,因为时间比较紧,所以这个例子我没放上来。


八、Non-FPW的思路


image.png

MySQL双写不能解决所有的问题,那我就摸着Oracle过河,Oracle的解决方案是报出错误,能够检测块的问题,检测不出来数据就不一致了,我提供让DB恢复,为了更快的恢复,也可以提供一个像Oracle一样的块恢复功能。MySQL不支持这样的功能,它是逻辑日志,只能恢复数据,不能恢复某一个固定的页。PG和Oracle都是物理日志,他们可以有black recovery的功能。

image.png

最终我们的方式是摸着Oracle过河,因为Oracle跟PG备份恢复体系差不多,检查点位置、特性都差不多,唯一不同的是Oracle是增量检查点,PG没有增量检查点,这点对我们影响不大。

目标是让PG实现跟Oracle一样检查加块恢复的功能,实现快速的不分写的解决方式。实现之后就可以安全的关掉FPW,不用担心出现断电后数据不一致的问题。

image.png

MySQL的恢复功能在StartupXLOG函数里面,这个函数在这个Xlog.c里面,在此if之后,就是它的恢复流程。

image.png

下面是要对这一部分代码去精读熟读,搞清楚每一行的意义,每个变量的作用等。在这个基础上去做修改调整,把它复制出来再自己做一个模块,用它做检查块和级恢复。

 

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
NoSQL 小程序 Java
微信开发框架WxJava之微信公众号开发的入门使用篇
WxJava是一款基于Java语言的微信开发Java SDK,它提供了微信支付,开放平台,小程序,企业微信,公众号等多个平台的API接口,并将其封装为易于调用的Java方法,方便Java开发者快速开发与微信相关的应用。
4447 1
|
存储
游戏开发实战教程(1)
现在学习编程似乎非常的热门,尤其是针对小孩子。各种培训机构教育机构都会有各种各样的编程课,宣传要尽早的培养孩子的编程思维,因为当前是互联网的时代,将来会编程可能会像每个人都会开车一样的成为一种必须的技能。
89 0
游戏开发实战教程系列
做一个不会过时的游戏。这个游戏的玩法很经典,经过市场的验证,如同俄罗斯方块一样不会过时。 做一个做完后不需要再去长期维护的游戏。做完了就是做完了,不需要再继续投入时间精力维护。 做一个精致的游戏。让人打开它后能够感受到这是一个精致的作品,会让人感觉到舒服。
97 0
|
存储
微信小游戏开发实战1-让计算机理解你的想法
本文内容主要包含我对编程思维的理解,以及1010游戏中的核心玩法的逻辑,我们如何进行设计并且让计算机能够理解。如果你没有任何的游戏开发经验,欢迎阅读我的“人人都能做游戏”系列教程,它会手把手的教你做出自己的第一个小游戏。
89 0
|
存储 JSON 小程序
小程序云开发实战总结|快速上手&场景实战(二)
基于微信小程序云开发,我搭建了两款百科类的小程序 我会从云开发基本能力与场景实战两个方面来总结一篇我的实战过程中的心得 希望这篇文章可以对刚接触云开发的掘友有所帮助。
214 1
小程序云开发实战总结|快速上手&场景实战(二)
|
存储 JSON 小程序
小程序云开发实战总结|快速上手&场景实战(一)
基于微信小程序云开发,我搭建了两款百科类的小程序 我会从云开发基本能力与场景实战两个方面来总结一篇我的实战过程中的心得 希望这篇文章可以对刚接触云开发的掘友有所帮助。
455 0
小程序云开发实战总结|快速上手&场景实战(一)
|
存储 前端开发 安全
云开发实战 | 学习笔记
简介:快速学习云开发实战
276 0
云开发实战 | 学习笔记
|
SQL 前端开发 Java
全栈开发实战|SSM框架整合开发
全栈开发实战|SSM框架整合开发
133 0
全栈开发实战|SSM框架整合开发
|
缓存 NoSQL Java
Spring Boot 2.5.x开发实战 | 开发者学堂课程干货总结合集
Spring Boot 2.5.x开发实战是学习Java Spring Cloud微服务架构的必经之路
2578 3
Spring Boot 2.5.x开发实战 | 开发者学堂课程干货总结合集
|
算法 Linux 开发工具
RVB2601应用开发实战 | 开发者社区精选文章合集(三十二)
RVB2601开发板是基于CH2601芯片设计的生态开发板,其具有丰富的外设功能和联网功能,可以开发设计出很多有趣的应用。本篇就来看几个实际应用开发。
RVB2601应用开发实战 | 开发者社区精选文章合集(三十二)