使用 PostgreSQL 管理 OCI 数据库中用于灾难恢复设置的 pglogical Replication 中的序列

简介

本教程概述了用于在主系统与灾难恢复 (Disaster Recovery,DR) 系统之间的逻辑双向复制设置中同步 PostgreSQL 序列值的定制解决方案。

问题陈述:

在当前设置中,我们配置了逻辑双向复制。某些复制的表依赖于序列;但是,我们发现这些序列的 last_value 不会在主环境和 DR 环境之间复制。

这是预期的行为,在 pglogical 中不被视为 bug。根据设计,序列值不会被复制,因为序列被视为非事务性的,并且本质上是特定于节点的,以避免冲突。

为了弥补这一差距,我们实施了一个定制解决方案来同步主系统和 DR 系统之间的序列值。具体而言,我们正在开发一种程序:

此方法可确保序列值在两个系统中保持一致,从而防止主要在 DR 环境中出现潜在的数据完整性或冲突问题。

目标

任务 1:设置 pglogical 双向复制

确保已在主系统和 DR 系统之间配置 pglogical 双向复制。

If not yet configured, follow the official documentation to set up pglogical accordingly: Set up pglogical Extension Replication in the Source Database.

任务 2:启用必需的扩展

在主系统和 DR 系统中,通过从 OCI 控制台创建配置来启用以下扩展。

在 DBSystems 上应用配置文件后,连接到每个 DBSystem 上的 postgres 数据库并运行以下查询。

CREATE EXTENSION IF NOT EXISTS pg_cron;
CREATE EXTENSION IF NOT EXISTS dblink;

任务 3:创建过程

postgres 数据库的主系统和 DR 系统上创建过程。

过程定义:

CREATE OR REPLACE PROCEDURE sync_sequences_from_remote()
LANGUAGE plpgsql
AS $$
DECLARE
  -- Update the connection string with correct credentials and hostname
  conn_str TEXT := 'host=<hostname> user=<username> password=<password> dbname=postgres';

  row RECORD;
  remote_seq_query TEXT :=
    $_$SELECT schemaname, sequencename, last_value
       FROM pg_sequences
       WHERE schemaname !~ 'pg_catalog|cron|information_schema|pg_toast|pg_temp'
         AND last_value IS NOT NULL$_$;
  full_seq_name TEXT;
  setval_sql TEXT;
BEGIN
  FOR row IN
    SELECT * FROM dblink(conn_str, remote_seq_query)
      AS t(schemaname TEXT, sequencename TEXT, last_value BIGINT)
  LOOP
    full_seq_name := quote_ident(row.schemaname) || '.' || quote_ident(row.sequencename);
    setval_sql := FORMAT('SELECT setval(%L, %s, true);', full_seq_name, row.last_value);
    RAISE NOTICE 'Setting sequence: %', setval_sql;
    EXECUTE setval_sql;
  END LOOP;
END;
$$;

注:

任务 4:在 DR 系统中创建 pg_cron 作业

运行以下查询以创建 pg_cron 作业,并安排该过程在 DR 数据库系统上每隔一分钟运行一次。

SELECT cron.schedule('UPDATE SEQUENCE', '*/1 * * * *', $$ CALL sync_sequences_from_remote(); $$);

注:

任务 5:在主系统中创建 pg_cron 作业并保持禁用状态

运行以下查询以创建 pg_cron 作业并禁用该作业。

SELECT cron.schedule('*/1 * * * *', $$ CALL sync_sequences_from_remote() $$);

-- Disable the job (on Primary)
SELECT cron.alter_job(jobid := <job_id>, active := false);

任务 6:处理故障转移

如果发生故障转移,请执行以下步骤:

  1. 在新的 DR(以前为 primary)中,启用 pg_cron 作业。

  2. 在新的主服务器(以前称为 DR)中,禁用 pg_cron 作业。

这可确保同步过程始终仅在当前 DR 系统上运行。

注:

确认

更多学习资源

通过 docs.oracle.com/learn 浏览其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。

有关产品文档,请访问 Oracle 帮助中心