首页 存档 技术 查看内容

从MySQL中的double write问题说开去

2018-3-30 13:00 |来自: 互联网 280 0

摘要: 作者介绍 杨建荣,DBAplus社群联合发起人。现就职于搜狐畅游,Oracle ACE、YEP成员,超7年数据库开发和运维经验,擅长电信数据业务、数据库迁移和性能调优。持Oracle 10G OCP,OCM,MySQL OCP认证,《Oracle DBA工作 ...


作者介绍

杨建荣DBAplus社群联合发起人。现就职于搜狐畅游,Oracle ACE、YEP成员,超7年数据库开发和运维经验,擅长电信数据业务、数据库迁移和性能调优。持Oracle 10G OCP,OCM,MySQL OCP认证,《Oracle DBA工作笔记》作者。


有句话说得好,世上只有两种工具,一种是被人骂的,另一种是没人用的。被骂得越多,侧面反映出关注度越高,使用率越高,越用越成熟,这一点上,MySQL就是一个很不错的例子。而MySQL可支持的存储引擎很多,目前以InnoDB最佳,算为上品。


自MySQL 5.5.5开始,InnoDB是作为默认的存储引擎,而之前MyISAM存储引擎其实也占有一席之地,但MySQL开发团队自宣布MySQL 8.0.0开发里程碑版本DMR开始,就把MySQL版本一下子从5.x跳跃到了8.0。其中的一个亮点就是事务性数据字典,完全脱离MyISAM存储引擎,所以InnoDB宝刀不老,是我们学习MySQL重点需要了解的存储引擎。而其中InnoDB的double write特性很有意思,也是我们今天讨论的重点内容。


其实在MySQL和Oracle都会面临这类问题,不过各自有着不同的解决方案。我也看到网上有很多DBA在这个地方纠结、争论。相比而言,Oracle这边更沉默一些。我看了他们的讨论,但目前为止还没有看到一个把两方面都照顾到的解读。所以我决定做这个事情,以此来对比MySQL和Oracle中的一些实现和差别。很多都是个人之言,所以有些说法不一定对,算是一次尝试,希望引起一些思考和讨论。


InnoDB中的double write


首先我们来说说InnoDB和double write。


InnoDB有三大闪亮特性:insert buffer、double write和自适应哈希,其实还有几个比如异步IO、Flush neighbour Page(刷新邻接页),这个和系统层面关联性较高,所以三大亮点还是有普适性的。


首先我们来简单了解一下double write为什么要这么设计、解决了什么样的问题。对此我画了一个相对简陋的图,还有很多细节没有照顾到,但是能够说明意思。



总体来说,double write buffer就是一种缓冲缓存技术,主要的目的就是为了防止数据在系统断电,异常crash情况下丢失数据。里面有几个点需要注意的就是,数据在buffer pool中修改后成了脏页,这个过程会产生Binglog记录和redo记录,当然缓存数据写入数据文件是一个异步的工作。如果细看,在共享表空间(system tablespace)中会存在一个2M的空间,分为2个单元,一共128个页,其中120个用于批量刷脏数据,另外8个用于Single Page Flush。


根据阿里翟卫祥同学分析,之所以这样做是因为批量刷脏是后台线程做的,这样不影响前台线程。而Single Page Flush是用户线程发起的,需要尽快地刷脏并替换出一个空闲页出来。所以不是一个严格的64 64的拆分,最后也给出了这篇文章的链接。(https://yq.aliyun.com/articles/50627


而数据刷新过程,是先使用memcopy把脏数据复制到内存中的double write buffer,分两次写完,每次写1MB到共享表空间,然后就是调用fsync来同步到磁盘。这里有一点需要注意的是,这个刷新到共享表空间的过程,虽然是两次,但是是顺序写,所以开销不会很大,也就不会像大家想象的那样,觉得double write性能可能很差。根据Percona的测试,大概也就是5%左右的差别,数据重要还是性能更重要,这是一个基本的命题。当然后续会再写入对应的表空间文件中,这个过程就是随机写,性能开销就会大一些。所以早些时候试用SSD时很多人也带有如此的顾虑,顺序写还是随机写,这个顾虑在这篇文章中也会有一些解释。


当然double write这么设计就是为了恢复而用,要不这么大张旗鼓就不值得了。对于文件校验来说,一个中心词就是checksum。如果出现了partial write的时候,比如断电,那么两次写的过程中,很可能page是不一致的,这样checksum校验就很可能出现问题。而出现问题时,因为有了前期写入共享表空间的页信息,所以就可以重构出页的信息重新写入。


double write其实还有一个特点,就是将数据从double write buffer写到真正的segment中时,系统会自动合并连接空间刷新的方式,这样一来每次就可以刷新多个pages,从而提高效率。


比如下面的环境,我们可以根据show status的结果来得到一个合并页的情况。


声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部