大家都知道,PostgreSQL 使用 MVCC 和 WAL 两项技术实现 ACID 特性。 MVCC 即多版本并发控制,简单的说,是数据库中的同一份有效数据,会同时保留多个修改版;用 snapshot 即快照,来定义一个事务能看到哪些版本的数据。

一个连接进行查询或修改数据时会开启一个事务(只读事务或读写事务),事务的可见性由事务中的快照决定。 也就是说,两个事务的快照相同,那么看到的数据是完全相同的。 PostgreSQL 9.3 开始,支持函数:pg_export_snapshot,它能返回一个快照的唯标识,便于其他事务也使用相同的快照查看数据。

详见:1.如何导出一个快照 Table 9-64. Snapshot Synchronization Functions

从 PostgreSQL 9.3 开始,支持开启一个事务到一个指定的的快照版本。

如果使用多个连接并行的备份数据库中的不同的表,在数据库还在同时修改数据库的状态下是无法获得一个完全一致的数据的。

这时,使用上述连个特性,我们可以在 PostgreSQL 9.3 和以上版本做到拿到一份一致版本的数据。 大致的步骤是

  • 1. 备份程序主进程连接数据库,开启只读事务,并使用函数 pg_export_snapshot 导出对应的snapshotid。
  • 2. 开启 N 个子进程,连接数据库,分别设置主进程中获得的 snapshotid,开始并行备份数据。

实际上 PostgreSQL 自带的逻辑备份和恢复工具在 9.3 和之后的版本就已经这么做了

1) pg_dump 的并行备份开关 -j

  • 注意:备份的并行粒度是以表为单位,且需要以 directory 模式备份数据,也就是备份数据到一个目录中,目录中每个表的数据都用一个或多个文件存放。
  • 该模式加上备份压缩开关,是效率最高的逻辑备份方式。

3.并行逻辑备份 pg_dump

然而,事情到这里还没有结束,如果用户的数据较多(例如TB级或以上),上述存全量的数据迁移方法对业务造成的影响也会很大(业务停机时间较长)。

PostgreSQL 9.4 开始,支持逻辑复制特性,能和上述特性完美的结合起来,做到接近 0 停机时间的业务迁移。

下面,让我慢慢道来。

PostgreSQL 逻辑复制(logical replication),原理是类似 MySQL binlog 同步,PostgreSQL 会启动一组后端进程,把数据库产生的 redo 日志(物理日志),解析成逻辑日志,并发送给客户端。转换成的逻辑数据可以通过插件的方式自定义。这个模块叫 logical decoding。

这份逻辑数据是灵活,完全由用户自定义,用户可以根据自己的需求定制

  • 存放一个比较简单的中间数据结构,做 PostgreSQL 到 PostgreSQL 间部分对象的数据迁移
  • 解析成标准的 SQL 语句,做 PostgreSQL 到异构数据库的增量数据迁移或持续同步

5. 逻辑流复制介绍

PostgreSQL 利用上述技术点,把一致的全量数据迁移和增量逻辑复制结合起来,做到在保证严格的数据一致性基础上的,接近 0 停业务时间的数据迁移服务。

数据迁移的步骤:

  • 1. 迁移程序主进程使用 CREATE_REPLICATION_SLOT 创建用户增量的逻辑 SLOT,记录数据同步的启始一致点(snapshotid)。这是数据一致性迁移的关键点,也是全量迁移和增量迁移的重要衔接点。

注意:

2) CREATE_REPLICATION_SLOT 不是一个 SQL 语句,是一个前后端的协议命令,它的返回结果集第四列是一个 snapshotid。snapshotid 的获取方法可以参考 pg_recvlogical –create-slot 的实现。

  • 3. 于此同时,为了避免数据库的 redo 日志在主库的堆积,客户端启动一个连接拉取增量日志,并解析成能够被目的数据库识别的数据,且持久化保存。

  • 4. 当任务 2 中的所有的全量同步任务完成之后,开始同步全量同步期间产生的增量数据(任务3中)。直到现存的增量数据都同步完,追平和主库的数据差异。

  • 5. 当数据接近追上时,停止主库写数据。

  • 6. 当数据完全追上后,开始数据校验。

  • 7. 数据校验完成后,应用开始连接目的端数据库,数据迁移完成,开始正常业务。

7. pg_recvlogical

  1. 上述该方案能做到严格数据一致的数据同步,且全量数据迁移和增量数据迁移无缝衔接。

  • 2)长时间的数据同步需要保存更多的状态信息,能做到任务的长期可运维,需要做到 DDL 的变更。