暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PolarDB-PG原理解读——DDL同步(下)

PolarDB农夫山泉 2023-08-25
220

PolarDB PostgreSQL版(以下简称 PolarDB-PG)是一款阿里云自主研发的企业级数据库产品,采用计算存储分离架构,兼容 PostgreSQL 与 Oracle。PolarDB-PG 的存储与计算能力均可横向扩展,具有高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB-PG 具有大规模并行计算能力,可以应对 OLTP 与 OLAP 混合负载;还具有时空、向量、搜索、图谱等多模创新特性,可以满足企业对数据处理日新月异的新需求。

如何保证数据正确性

DDL 锁是 PostgreSQL 数据库最高级别的锁,当对一个表进行 DROP / ALTER / LOCK / VACUUM (FULL) table 等操作时,需要先获取到 DDL 锁。RW 是通过用户的主动操作来获取锁,获取锁成功时会写入到日志中,RO 则通过回放日志获取锁。

  • 主备环境:热备存在只读查询,同时进行回放,回放到该锁时,如果该表正在被读取,回放就会被阻塞直到超时
  • PolarDB-PG 环境:RW 获取锁需要等待 RO 全部获取锁成功才算成功,因为需要确保主备都不再访问共享存储的数据才能进行 DDL 操作

当以下操作的对象都是某张表,< 表示时间先后顺序时,同步 DDL 的执行逻辑如下:

  1. 本地所有查询操作结束 < 本地获取 DDL 锁 < 本地释放 DDL 锁 < 本地新增查询操作
  2. RW 本地获取 DDL 锁 < 各个 RO 获取本地 DDL 锁 < RW 获取全局 DDL 锁
  3. RW 获取全局 DDL 锁 < RW 进行写数据操作 < RW 释放全局 DDL 锁

结合以上执行逻辑可以得到以下操作的先后顺序:各个 RW / RO 查询操作结束 < RW 获取全局 DDL 锁 < RW 写数据 < RW 释放全局 DDL 锁 < RW / RO 新增查询操作

可以看到在写共享存储的数据时,RW / RO 上都不会存在查询,因此不会造成正确性问题。在整个操作的过程中,都是遵循 2PL 协议的,因此对于多个表,也可以保证正确性。

RO 锁回放优化

上述机制中存在一个问题,就是锁同步发生在主备同步的主路径中,当 RO 的锁同步被阻塞时,会造成 RO 的数据同步阻塞(如图 1 所示,回放进程的 3、4 阶段在等待本地查询会话结束后才能获取锁)。PolarDB-PG 默认设置的同步超时时间为 30s,如果 RW 压力过大,有可能造成较大的数据延迟。

RO 中回放的 DDL 锁还会出现叠加效果,例如 RW 在 1s 内写下了 10 个 DDL 锁日志,在 RO 却需要 300s 才能回放完毕。数据延迟对于 PolarDB-PG 是十分危险的,它会造成 RW 无法及时刷脏、及时做检查点,如果此时发生崩溃,恢复系统会需要更长的时间,这会导致极大的稳定性风险。

异步 DDL 锁回放

针对此问题,PolarDB-PG 对 RO 锁回放进行了优化。

image.png异步回放ddl锁.png
图 4:RO 异步 DDL 锁回放

优化思路:设计一个异步进程来回放这些锁,从而不阻塞主回放进程的工作。

整体流程如图 4 所示,和图 3 不同的是,回放进程会将锁获取的操作卸载到锁回放进程中进行,并且立刻回到主回放流程中,从而不受锁回放阻塞的影响。

锁回放冲突并不是一个常见的情况,因此主回放进程并非将所有的锁都卸载到锁回放进程中进行,它会尝试获取锁,如果获取成功了,就不需要卸载到锁回放进程中进行,这样可以有效减少进程间的同步开销。

该功能在 PolarDB-PG 中默认启用,能够有效的减少回放冲突造成的回放延迟,以及衍生出来的稳定性问题。在 AWS Aurora 中不具备该特性,当发生冲突时会严重增加延迟。

如何保证数据正确性

在异步回放的模式下,仅仅是获取锁的操作者变了,但是执行逻辑并未发生变化,依旧能够保证 RW 获取到全局 DDL 锁、写数据、释放全局 DDL 锁这期间不会存在任何查询,因此不会存在正确性问题。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论