MySQL : 基于InnoDB的物理复制实现

本文详细介绍了在MySQL中基于InnoDB实现物理复制的原理与过程,包括事务ID、Read View、Redo Log等核心概念。文章讨论了原生复制的优缺点,并解释了为何需要物理复制以提升性能。物理复制减少了日志写入,提高了吞吐量,通过并发apply和减少延迟以提高复制性能。文章还涵盖了复制架构、实例角色、后台线程管理和DDL复制等方面的内容。
摘要由CSDN通过智能技术生成

最近有幸前去美国参加Percona Live 2016会议并分享了我们最近在MySQL复制上所做的工作,也就是基于InnoDB的物理复制。会后很多小伙伴私信我说分享的PPT太内核了,不太容易理解。因此本文主要针对分享的内容进行展开描述,希望能对大家有所帮助。

背景知识

在开始之前,你需要对InnoDB的事务系统有个基本的认识。如果您不了解,可以参考我之前的几篇关于InnoDB的文章,包括InnoDB的事务子系统,事务锁,redo log,undo log,以及崩溃恢复逻辑。在这里我们简单的概述一下几个基本的概念:

事务ID:一个自增的序列号,每次开启一个读写事务(或者事务从只读转换成读写模式)时分配并递增,每更新256次后持久化到Ibdata的事务系统页中。每个读写事务都必须保证拥有的ID是唯一的。

Read View:用于一致性读的snapshot,InnoDB里称为视图;在需要一致性读时开启一个视图,记录当时的事务状态快照,包括当时活跃的事务ID以及事务ID的上下水位值,以此用于判断数据的可见性。

Redo Log:用于记录对物理文件的修改,所有对InnoDB物理文件的修改都需要通过Redo保护起来,这样才能从崩溃中恢复。

Mini Transaction(mtr):是InnoDB中修改物理块的最小原子操作单位,同时也负责生产本地的redo日志,并在提交mtr时将redo日志拷贝到全局log buffer中。

LSN:一个一直在递增的日志序列号,在InnoDB中代表了从实例安装到当前已经产生的日志总量。可以通过LSN计算出其在日志文件中的位置。每个block在写盘时,其最近一次修改的LSN也会记入其中,这样在崩溃恢复时,无需Apply该LSN之前的日志。

Undo Log:用于存储记录被修改之前的旧版本,如果被多次修改,则会产生一个版本链。保留旧版本的目的是用于可重复读。通过结合Undo和视图控制来实现InnoDB的MVCC。

Binary Log:构建在存储引擎之上的统一的日志格式;有两种存储方式,一种是记录执行的SQL,另外一种是记录修改的行记录。Binlog本质上是一种逻辑日志,因此能够适用所有的存储引擎,并进行数据复制。

原生复制的优缺点

MySQL的每条读写事务都需要维持两份日志,一份是redo log,一份是binary log。MySQL使用两阶段提交协议,只有当redo 和binlog都写入磁盘时,事务才算真正的持久化了。如果只写入redo,未写入binlog,这样的事务在崩溃恢复时需要回滚掉。MySQL通过XID来关联InnoDB的事务和binlog。

MySQL的原生事务日志复制有一些显著的优点:

首先,相比InnoDB的redo log而言,Binary Log更加可读,有成熟的配套工具来进行解析;由于记录了行级别的更改。我们可以通过解析binlog,转换成DML语句来将数据变更同步到异构数据库。另外一种典型的做法是使用Binlog来失效构建在前端的cache。事实上,基于Binlog的数据流服务在阿里内部使用的非常广泛,也是最重要的基础设施之一。

其次由于Binary log是一种统一的日志格式,你可以在主备上使用不同的存储引擎,例如当你需要测试某种新的存储引擎时,你可以搭建一个备库,将所有表alter到新引擎,然后开启数据复制进行观察。

此外基于Binary Log你还可以构建起非常复杂的复制拓扑结构,尤其是在引入了GTID之后,这种优势尤为明显: 如果设计妥当,你可以实现相当复杂的复制结构。甚至可以做到多点写入。总体使用起来非常灵活。

然而,也正是这种日志架构可能会带来一些问题:首先MySQL需要记录两份日志:redo及binlog,只有当两份日志都fsync到磁盘,我们才能认为事务是持久化的,而众所周知,fsync是一种开销非常昂贵的操作。更多的日志写入还增加了磁盘IO压力。这两点都会影响到响应时间和吞吐量。

Binlog复制还会带来复制延迟的问题。我们知道只有主库事务提交后,日志才会写入到binlog文件并传递到备库,这意味着备库至少延迟一个事务的执行时间。另外有些操作例如DDL,大事务等等,由于在备库需要继续保持事务完整性,这些执行时间很长的操作会长时间占用某个worker线程,而协调线程会碰到复制同步点,导致后续的任务无法分发到其他空闲的worker线程。

MySQL是原生复制是MySQL生态的一个非常重要的组成部分。官方也在积极的改进其特性,例如MySQL5.7在这一块就有非常显著的改进。

Why Phsyical Replication

既然原生复制这么成熟,优点这么多,为什么我们还要考虑基于物理日志的复制呢?

首先最重要的原因就是性能!当我们事先了物理复制后,就可以关闭binlog和gtid,大大减少了数据写盘量。这种情况下,最多只需要一次fsync既可以将事务持久化到磁盘。实例整体的吞吐量和响应时间都得到了非常大的提升。

另外,通过物理复制,我们能获得更加理想的物理复制性能。事务在执行过程中产生的redo log只要写到文件中,就会被传送到备库。这意味着我们可以同时在主备库上执行事务,而无需等待主库上执行完成。我们可以基于(space_id, page_no)来进行并发apply,同一个page上的变更也可以做到合并写操作,相比传统复制,具有更好的并发性。最重要的是,基于物理变更的复制,可以最大程度保证主备的数据总是一致的。

当然物理复制不是银弹,当启用该特性后,我们将只能支持InnoDB存储引擎;我们也很难去设计多点写复制拓扑。物理复制无法取代原生复制,而是应对特定的场景,例如需求高并发DML性能的场景。

因此在正式开始前,我们设置了这些前提:1.主库上不应该有任何限制; 2.备库上只允许执行查询操作,不允许通过用户接口对数据产生任何的变更。

下文默认MySQL已包含如下特性:

没有只读事务链表,并且不为只读事务分配事务ID

使用全局事务ID数组来构建read view快照

所有MySQL库下的系统表都使用InnoDB存储引擎

High Level Architecture

复制架构<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农老K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值