逻辑复制核心概念与复制槽机制
PostgreSQL的逻辑复制基于WAL(Write-Ahead Log)解析,将数据变更以逻辑行级格式传播到订阅端。与物理复制不同,逻辑复制不要求目标实例与源实例完全一致,支持跨版本、跨操作系统、选择性复制表和列。
逻辑复制槽(Logical Replication Slot)是核心组件,确保WAL段在订阅端消费前不会被回收。创建发布者时自动创建复制槽:
-- 源库:创建发布
CREATE PUBLICATION mig_pub FOR TABLE users, orders, products
WITH (publish = 'insert, update, delete');
-- 查看复制槽状态
SELECT slot_name, plugin, slot_type, active,
restart_lsn, confirmed_flush_lsn
FROM pg_replication_slots;
confirmed_flush_lsn 表示订阅端已确认消费的LSN位置。如果订阅端长时间断开,WAL会持续堆积,可能导致磁盘溢出。建议设置 wal_keep_size 限制WAL保留量,并监控复制延迟。
零停机迁移的整体方案设计
零停机迁移的核心流程:逻辑复制建立初始同步到增量变更持续复制到验证数据一致性到切换流量。
-- 目标库:创建订阅(初始数据自动复制)
CREATE SUBSCRIPTION mig_sub
CONNECTION 'host=source-db port=5432 dbname=appdb user=replicator password=xxx'
PUBLICATION mig_pub
WITH (copy_data = true, streaming = 'parallel');
copy_data = true 自动完成初始全量数据拷贝。streaming = 'parallel' 启用并行流式复制(PG 17+),大事务的变更边产生边传输,而非等事务提交后批量发送,显著降低大事务的复制延迟。
大表并行初始同步加速
单表超过千万行时,默认的单进程COPY可能需要数小时。PostgreSQL 17支持并行初始同步:
-- 目标库创建带并行参数的订阅
CREATE SUBSCRIPTION mig_sub
CONNECTION 'host=source-db port=5432 dbname=appdb user=replicator'
PUBLICATION mig_pub
WITH (
copy_data = true,
streaming = 'parallel',
max_parallel_workers = 4
);
源端调优参数:
-- 源库:增大WAL发送缓冲
ALTER SYSTEM SET wal_sender_timeout = '60s';
ALTER SYSTEM SET max_wal_senders = 10;
ALTER SYSTEM SET logical_decoding_work_mem = '256MB';
ALTER SYSTEM SET max_replication_slots = 10;
-- 降低磁盘写入延迟
ALTER SYSTEM SET wal_writer_delay = '10ms';
ALTER SYSTEM SET commit_delay = 5000; -- 微秒
SELECT pg_reload_conf();
logical_decoding_work_mem 控制逻辑解码的内存预算。增大此值减少磁盘溢出次数,对于高写入场景从默认64MB调至256MB可提升约40%的解码吞吐。
数据一致性校验方法
同步完成后,切换流量前必须校验数据一致性:
-- 行数对比
SELECT 'users' AS tbl,
(SELECT count(*) FROM users) AS src_count,
(SELECT count(*) FROM target.users) AS tgt_count;
-- 校验和对比(适合中小表)
SELECT md5(string_agg(t::text, ',' ORDER BY id))
FROM (SELECT * FROM users ORDER BY id) t;
-- 大表采样校验
SELECT id, md5(row_to_json(t)::text)
FROM users TABLESAMPLE BERNOULLI(0.1)
WHERE id > 1000000
ORDER BY id;
生产环境推荐使用 pglogical 或 pg_repack 的校验工具,它们支持增量对比和差异报告。也可自建校验脚本,按主键范围分片并行计算哈希,将校验时间从小时级压缩到分钟级。
流量切换与回滚方案
切换时机选择逻辑复制延迟趋近于零时:
-- 查看复制延迟
SELECT now() - pg_last_xact_replay_timestamp() AS replay_lag;
-- 当replay_lag < 1秒时,执行切换
-- 1. 源库设为只读
ALTER DATABASE appdb SET default_transaction_read_only = true;
-- 2. 等待复制槽消费完所有残余WAL
SELECT slot_name, pg_current_wal_lsn() - confirmed_flush_lsn AS lag
FROM pg_replication_slots;
-- 3. 目标库断开订阅
ALTER SUBSCRIPTION mig_sub DISABLE;
ALTER SUBSCRIPTION mig_sub SET (slot_name = NONE);
DROP SUBSCRIPTION mig_sub;
-- 4. 切换应用连接串
回滚预案:保留源库的只读状态而非直接关闭,一旦目标库出现问题,将应用连接切回源库并解除只读即可。整个回滚可在分钟级完成。
常见问题与排障指南
复制槽堆积导致磁盘满:订阅端断开后WAL不回收。设置 wal_keep_size = '2GB' 限制保留量,同时配置 pg_replication_slot 监控告警。紧急时用 pg_drop_replication_slot() 强制删除。
大事务阻塞复制:单事务超过 logical_decoding_work_mem 会导致磁盘溢出。PG 17的streaming=parallel模式缓解了此问题,但仍建议业务层拆分大事务,单事务影响行数控制在10万以内。
DDL变更不复制:逻辑复制仅传播DML,DDL需在两端手动执行。建议使用Liquibase或Flyway统一管理Schema变更,确保源端和目标端结构一致。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql17-luo-ji-fu-zhi-cao-yu-ling-ting-ji-qian-yi-shi/