关于sql:TDSQL-DTS-for-PostgreSQL-逻辑复制详解

3次阅读

共计 6128 个字符,预计需要花费 16 分钟才能阅读完成。

逻辑复制概念

逻辑复制是 PG 数据库基于数据对象的复制标记,也就是 Replica Identity 来复制数据对象及数据变动的办法。它最后是在 2014 年 12 月份的 PG9.4.0 引入,称为逻辑解码,起初在 2017 年 10 月 PG10.0 版本中又引入了基于公布订阅的逻辑复制概念。之所以称为逻辑复制是为了和更早引入的物理复制加以辨别。逻辑复制法则和物理复制这两种复制机制有比拟大的区别,物理复制是应用精确的块地质陈迹逐字节的复制形式,而逻辑复制则容许在数据层面复制,并在安全性上提供更细粒度的管制。

逻辑复制性能演进大抵分为两个比拟大的阶段,第一阶段是 2014 年 12 月份,随着 9.4.0 版本公布,PG 为 DML 带来数据批改流动到内部提供基础设施,用户能够基于它实现复制解决方案和审计等目标。数据批改以流的模式收回,通过逻辑复制槽 Replication Slot 来辨认,配合解码插件 Decoding Plugin,实现每一份数据批改在每一个流中输入。

同时 PG 基于 WAL 日志作为原始输入,Slot 保障数据流的唯一性,Decoder 插件赋予用户自定义输入能力,来做到将 PG 实例的数据变动流动到内部。第二阶段是 2017 年 10 月 4.0 版本的公布,PG 逻辑复制提供了公布和订阅模型,外部和订阅能够是多对多关系,例如容许有一个或多个订阅者来订阅同一个实例上多个公布。订阅者与发布者雷同程序,利用数据变更实现在同一个订阅中保障公布事务的一致性,这种数据复制形式有时候被称为事务性复制。

数据迁徙的利用场景及宏观的技术架构

上面介绍迁徙的利用场景跟宏观的技术架构。数据迁徙产品对云上的数据库,私有云数据库是一个避不开的话题,也是用户数据上云的一个入口。云上数据迁徙产品可能帮客户在利用不停服前提下轻松实现数据迁徙上云,利用实时同步通道轻松构建高可用数据库容灾架构,通过数据订阅来满足商业数据挖掘、利用异步解耦等场景需要。

多个起源数据库要通过迁徙产品将数据转移到云上,包含 IDC 自建、其余云厂商、腾讯云本人的数据库及 CVM 自建等。为了稳固牢靠不便地实现用户迁云同步订阅需要,咱们定下了一致性、高性能、高可用的架构设计指标,在数据库类型上有多款数据库,不仅要实现同构迁徙,还要实现异构数据库迁徙,这是一个整体的数据迁徙利用场景。

插入 PPT 图片

迁徙场景总的技术架构,首先产品要具备向用户提供 API 和管制页面能力,就像这张图的最上层,其次是通过插件式的热加载,实现不同链路迁徙利用疾速接入,比如刚刚说的既有同构,也有异构。同构有多种数据库类型,异构同样有多种数据库类型,而且是 N×N 的链路组合。

看一下两头局部,工作执行平台,它不仅可能提供任务调度能力,还将组件高可用、监控告警、工作编排、运维零碎等纳入其中,做到了对前台高可用高牢靠,对后盾好运维、好接入的指标。图正下方这个区域,Node Server 是具体执行迁徙节点,能够把它看成是干事,具体干迁徙这件事件的一个节点或过程,它不仅可能疾速扩容,还可能动静负载平衡,实现全量和增量、并列、同步等工作。这个技术架构反对了腾讯云所有数据库类型的迁徙利用。

接下来回到 PG 逻辑复制,重点介绍逻辑复制外部的概念和原理。首先是比拟根底但又比拟重要的概念,复制标识是一个感知属性,它是用来管制表中记录被更新或改删除时写入 WAL 的内容,这个属性它只用于逻辑复制,并只能够通过 ALTER LABLE 来进行批改。同时须要留神的是,表中记录至多有一个列值发生变化了才会产生批改记录。感知属性有四个可感知,别离是 DEFAUTL、USINGINDEX、FULL、NOTHING,其中 FULL 和 NOTHING 这两个值比拟好了解,FULL 是指当记录变更时写入 WAL 日志的内容将包含所有字段原始值和所有字段的旧值。

例如表 T 它有三个字段 ABC,那么它记录了三个字段的原始值别离是 123,当这条记录产生变更时,PG 会把这个变更记录写到 WAL 日志内容,把 A=1、B=2、C=3 都放进去,也就是说让这个内容的消费者,不论是开发者还是应用程序,都可能失去这几个字段的旧值与原始值,NOTHING 是不计入任何旧值。

然而 DEFAUTL 和 USINGINDEX 这两个放在一起了解,DEFAUTL 就是把组件波及到的字段放在 WAL 日志内容中,比方说 T 表有 ABC 三个字段,如果 A 字段是主键,那么 DEFAUTL 会只把 A 主键 A 字段组件波及到的字段放到 WAL 日志内容中。USINGINDEX 比拟非凡,它是记录索引相干列的旧值,然而它要求索引必须是惟一线索引,必须是局部索引,也不能是延期索引,并且其中也不能包含空列。另外它是惟一键,不能为空,这可能是必须常见的 case,这时它容许用户指定,比如说指定哪个索引它就会用到哪个索引相干字段,这样相干字段旧值输出到 WAL 日志内容中。

那么如何来读取和生产这些 WAL 内容?如果把 WAL 视为一个仓库,每个复制槽 Replication Slot 则能够视为这个仓库诸多窗户。通过窗户能够读取仓库外面的内容,也就是数据变更。同时复制槽也记录着生产位点,能够保障每个数据变动它是被惟一地生产,并且是有序的。

多个复制槽之间互相位点是独立记录的,不能互相烦扰,同时生产输入的解码插件也是独立的,不同消费者能够在同一个 WAL 日志上通过申请不同的复制槽失去本人想要的数据内容,这个是复制槽的概念。

插入 PPT 图片

在迁徙中除了生产 WAL 日志失去数据变更内容外还有更广泛表的存量数据有待读取生产,在很多场景中存量数据的体量甚至要远远大于数据变更的体量,这时就要用到快照读方法。当两个或者更多会话须要查看数据库中雷同内容时,PG 容许一个事务导出它正在应用的快照,只有事务放弃关上,其余事务就能够导入这个快照,来保障这些事务看到的数据和第一个会话中事务看到的完全一致。

创立快照有两种形式,第一种是利用 CREATE_REPLICATION_SLOT 命令,在创立复制槽时主动创立快照,并保障事务一致性。第二个是应用零碎函数 pg_export_snapshot() 来导出快照。应用这两种形式都能够失去一个快照标记,当事务接入前,在其余事务中导入快照便能看到与以后事务完全相同的数据。

在可能实现复制槽快照之间事务一致性后,咱们晓得复制槽能够生产数据变更,也就是增量数据,快照能够读取存量数据,保障二者之间的事务一致性,那么咱们能够去牢靠地开启存量和数据读取了。后面所提到,通过 CREATE_REPLICATION_SLOT 来实现复制槽和快照同时创立,须要两个连贯会话。如图所示,关上一个 HelperConn,利用它来开启事务,创立复制槽和快照,记录下复制槽和快照的标记,而后关上第二个会话,在这个会话里开启事务,导入刚刚的快照标记,这样就可能实现增量数据和存量数据的读取和传输。通过两个会话咱们就能够把一种同时读取和传输的形式启动起来。

插入 PPT 图片

有了刚创立好的复制槽,接下来应该去关注如何将原始复制槽中读取的内容变更到指标实例。后面有提到 PG 逻辑复制是以 Decoder 插件赋予用户自定义输入格局的能力,那么这个插件到底如何去自定义?PG 内置一个非常简单的插件实现,代码在 contrib 目录下,叫 test_decoding,它的实现逻辑仅仅对数据变更值做简略打印,然而整体比拟丰盛,插件实现就是为 PG_output_plugin_init 函数提供回调实现,然而在 test_decoding 实现的根底上做批改,咱们能够将构造和数字拼接成能够执行的四个五句,便于咱们间接执行来进行回放。

接下来完结一下公布订阅基本原理,公布订阅前有提到是在 2017 年 10 月份在 10.0 版本中引入,将 SLOT 生产和回放,包含解码插件进行了封装,让用户免于操作复制槽、快照读、解码插件等一系列底层性能,不便取得稳固的全量加增量的数据迁徙通道。

用户只需简略在云端创立公布,在指标单创立订阅,并保障指标单到云端的网络连通性,就能够轻松实现一个迁徙链路。但须要留神几点,第一,公布时如果要整个库下的所有表,应用 FOR ALL TABLES 语法必须要用 superuser 权限。第二点,对于无主键表,如果应用默认的 DEFAUTL 复制标记,会导致源表的应用产生问题。第三点,受限于版本,版本 10 只反对 Insert、Delete、Update 三种语句,而版本 11 减少了对 Truncate 语句反对。第四,DDL 变更无奈被主动执行。第五,序列无奈主动复制,只能依附利用自行迁徙的。最初是公布订阅只反对字段计算表,对于分区表、表面以及大对象都是不反对的,理论应用中要更加留神。

解决方案

上面一起通过实在场景案例来看看咱们遇到的问题以及咱们的解决方案。首先看网络连通性问题,在后面屡次提到,云上数据库为了保障安全性肯定不会轻易放开实例对外部网络的拜访,当然不同网络架构下可能放开水平有所不同,这里只是强调在逻辑复制的利用场景上,云上实例对于公网地址个别不容许拜访。这样在内部公网实例上云时,基于逻辑复制,首先就会遇到网络连通性问题。

9.4 版本中逻辑复制对于源实例从公网进入内网要用到网络代理,有了代理后问题就会转化成内网实例间的连贯,这时迁徙节点 Node Server 会先进行存量数据的近程传输,而后用到两头存储 COS 服务,这是腾讯云的存储服务,来进行增量数据的生产和回放。这个过程中,数据始终被迁徙节点被动推动到指标实例来,构造比较简单,就是 Node Server 被动拿数据,而后把数据推到指标实例。

10 以上版本用到的是公布订阅场景,有一个指标实例反向拉取源实例的数据链路,这时迁徙节点 Node Server 齐全变成管制节点,来管制公布订阅的创立、启动、删除等生命周期,在公布订阅失效期间指标实例通过网络代理间接拉去源实例数据形成数据链路。

再看一个问题,对于无主键表的增量迁徙。后面提到一张表的复制标记管制这张表的数据批改,删除时写入 WAL 内容,此时对无主键表这一种非凡类型表进行剖析,能够得悉如果不批改复制标记,也就是放弃默认 DEFAUTL 标记,万一没有主键将无奈输入数据变更到 WAL 日志内容中。如果将复制标记设为 FULL 会怎么样呢?它无奈保证数据的一致性。咱们在图中放了一个例子。如果在源实例侧有一张无主键表,名叫 TB,它外面有两个字段别离是 id 和 name,能够看左边的 SQL 语句。有三条记录,在存量迁徙中这三条记录都曾经被迁徙过来了。而后对源表进行数据批改,删除其中一条记录,留神是以 ctid 的形式来删除。ctid 是什么?它是数据行所处的表内物理地位,而且会随着数据行在快内物理地位挪动而变动,无奈被逻辑复制标记所辨认。在指标端,因为应用了 FULL 复制标记,咱们晓得它批改之前的值。能够失去源端 id 等于 1、name 等于 Alice 的记录,利用这个条件咱们来做回放,就会一次性地删除三项记录。

能够看到 SQL 语句源实例只删除了一条,指标实例删除了多条,这样不一致性就呈现了。这是十分底层的问题,以 ctid 物理地位进行数据批改的形式尽管不推动,然而在理论场景中却无奈做出限度。这个形式是可行的,就肯定有可能有用户这么做。咱们能做的就是在迁徙预查看的过程中提醒用户去批改表构造,遵循正当的数据库设计规范,无主键表不是一个正当的设计实际,同时再将可能呈现数据不统一的危险裸露进去,提醒给用户。

接下来第三个问题,如何实现 DDL 主动同步。咱们晓得逻辑复制包含公布订阅都无奈实现主动同步 DDL 变更,在理论场景中,特地是在产品无奈实现而咱们又防止不了在迁徙过程中对构造进行变更。一个最罕用的场景就是很多数据分析利用场景中有分区表或者计程表,它们的创立和删除动作会一直去创立新的分区和删除老的分区场景。就能够通过其余形式,通过利用上的形式来实现手动或半自动的 DDL 主动同步。

第一种形式是什么?迁徙利用主动探测源端和指标端的构造差别,生成差别 DDL 变更至指标。咱们定时去做构造比照,比照进去差别 DDL 咱们再默认做一下执行,让它的构造变得更源端是一样的。这样做的长处是什么?不须要什么非凡权限,只有你应用迁徙过程中的 superuser 权限就能够,也不须要装置额定插件,因为做构造比照逻辑都是迁徙利用来实现。毛病是什么呢?它无奈保证数据的一致性,事务一致性,只可能利用在比较简单的场景。无奈保证数据的事务一致性。举个例子,比照源端和指标端构造时,源端构造变更变动曾经产生了一段时间,不可能说及时的实时去探测。在一段时间后在这个工夫区间内源端产生后到你探测到之前这段时间,如果产生了数据变更,这时你是获取不到的,要么是获取到然而你无奈变更的指标,因为指标没有这个构造或构造不统一而无奈去回放。

插入 PPT 图片

第二种办法是应用事件触发器来追踪表构造变更,并记录到一张非凡的表。事件触发器是 PG 里的机制,它须要一些操作权限,能做到一个库里的表发生变化,通过触发器的模式去跟踪记录。长处是可初步保障事务一致性,因为始终在跟踪它,那么它发生变化了就会第一工夫,只有变更事务提交了它就会被监测到,而后写到一张非凡表里。如果把这个非凡的表也放到一个逻辑复制里去追踪它的增量日志,那么它肯定和其余的变更程序是统一的,因为 SLOT 保障了数据变更程序是惟一的且有序的。长处是可初步保障这个毛病是它须要 superuser 权限,这个权限一般来讲是社区版是操作不了的。

第三个办法是装置内部插件来解析 WAL,在 Slot 中增加 DDL 相干信息,原始逻辑复制变更到指标。它的长处是能够保障事务一致性,因为应用原生的逻辑复制机制,然而毛病是目前这些插件都是第三方不是社区原生,另外它须要源实例的运维和插件装置权限。

遇到的挑战

接下来和大家分享在云上做 PG 迁徙利用会有哪些挑战如何去应答。咱们从分安全性、碎片化和社区追随这三个方面来看,首先是安全性,随着云上数据库技术的一直倒退演进,各厂商都锻炼出了针对本身定制的网络安全规定和数据库用户权限体系,相较于传统迁徙场景的齐全复制,咱们须要按源和指标各自的平安规定,来定制迁徙策略。例如在不同厂商之间迁徙,数据库账号权限点不尽相同,思考到各个厂商的安全策略,为了顺利完成迁徙,就须要对账号权限点做适当裁剪。这个是因为各种平安规定所导致,这是在迁徙利用中要去应答的第一个挑战。

第二个挑战是碎片化,PG 是一个开源、商业敌对的数据库,基于 PG 的数据库发行厂商也十分多,在内核架构上有着大大小小的差异性。为了提供这些对各个发行厂商更好的服务,咱们必须继续地针对各个发行厂商的产品做适配,给用户带来更好的应用体验。

最初是社区追随,PG 有一个弱小的社区,在社区版本迭代中,会有继续一直的个性变更和演进。以迁徙场景为例,社区 11 版本删除了 abstime、reltime、tinterval 这三种数据类型,逻辑复制又减少了对 truncate 的反对,因而咱们在做 11 版本之前,迁徙到 11 及当前的版本时,就要针对这种变动去做适配和反对。再举个例子,社区 13 版本中的逻辑复制减少了对分级表附表的反对,因而版本间的迁徙链路也须要随之一直迭代。后续咱们将持续跟进社区和云数据库本身内核演进一起,做更好的数据库迁徙解决方案。

正文完
 0