PostgreSQL逻辑复制基础原理
PostgreSQL逻辑复制是10版本引入的原生功能,区别于物理复制(基于WAL字节流复制整个实例),逻辑复制基于逻辑解码(Logical Decoding)解析WAL日志中的行级变更事件,以逻辑层面(INSERT/UPDATE/DELETE)的形式发布和订阅,可实现选择性复制(仅复制部分表或部分列)、跨版本复制、异构数据库同步等场景。逻辑复制的核心组件包括:Publication(发布端,定义要复制的表和操作类型)、Subscription(订阅端,连接发布端并应用变更)、Replication Slot(复制槽,保证WAL日志在订阅端确认前不被清理)、Output Plugin(输出插件,默认pgoutput,将WAL解析为逻辑变更事件)。
发布端配置与Publication创建
发布端需修改postgresql.conf开启逻辑复制支持,并配置wal_level为logical:
# postgresql.conf
wal_level = logical
max_wal_senders = 10
max_replication_slots = 10
wal_keep_size = 1024 # MB,保留WAL日志量
修改pg_hba.conf允许订阅端通过复制协议连接:
# pg_hba.conf
host replication replicator 10.0.2.0/24 md5
创建复制专用用户和Publication:
-- 创建复制用户
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secure_pwd_123';
-- 创建Publication,指定表和操作类型
CREATE PUBLICATION pub_users FOR TABLE users, user_profiles
WITH (publish = 'insert, update, delete');
-- 查看Publication状态
SELECT * FROM pg_publication;
SELECT * FROM pg_publication_tables;
publish参数控制复制哪些DML操作,默认all(insert+update+delete),可根据业务需求裁剪。
订阅端配置与Subscription创建
订阅端创建Subscription连接发布端,自动开始数据同步:
-- 创建Subscription
CREATE SUBSCRIPTION sub_users
CONNECTION 'host=10.0.1.11 port=5432 dbname=prod user=replicator password=secure_pwd_123'
PUBLICATION pub_users
WITH (
copy_data = true, -- 初始同步时复制存量数据
create_slot = true, -- 自动创建复制槽
enabled = true,
slot_name = 'sub_users_slot'
);
-- 查看同步状态
SELECT * FROM pg_subscription;
SELECT * FROM pg_stat_subscription;
pg_stat_subscription视图的received_lsn和latest_end_lsn字段反映复制进度,两者差距过大说明存在复制延迟。
复制冲突检测与处理
逻辑复制中常见的冲突场景包括:订阅端主键冲突、订阅端数据被直接修改导致UPDATE/DELETE找不到行、复制的数据类型不兼容。冲突发生时复制会停止,需手动处理。查看冲突日志:
-- 查看订阅端日志中的冲突信息
-- /var/log/postgresql/postgresql-*.log
-- 关键字:CONFLICT、duplicate key、could not find
-- 查看复制槽状态
SELECT slot_name, plugin, slot_type, active, restart_lsn
FROM pg_replication_slots;
-- 跳过冲突事务(需谨慎操作)
ALTER SUBSCRIPTION sub_users DISABLE;
-- 手动修复冲突数据后
ALTER SUBSCRIPTION sub_users ENABLE;
生产环境建议在订阅端设置repl_role权限限制,避免业务直接修改复制表数据,从根源消除冲突。
双向复制与多活架构实现
双向复制(Active-Active)要求两端互为发布和订阅,需处理循环复制问题(A的变更复制到B后,B不应再将该变更复制回A)。PostgreSQL通过Origin机制(11+)实现循环过滤:每个Subscription关联一个origin_id,应用复制数据时打上该标记,避免重复复制。
-- 节点A配置
CREATE PUBLICATION pub_a FOR TABLE users;
CREATE SUBSCRIPTION sub_from_b
CONNECTION 'host=10.0.2.11 ...'
PUBLICATION pub_b
WITH (origin = 'node_b');
-- 节点B配置
CREATE PUBLICATION pub_b FOR TABLE users;
CREATE SUBSCRIPTION sub_from_a
CONNECTION 'host=10.0.1.11 ...'
PUBLICATION pub_a
WITH (origin = 'node_a');
双向复制需保证表有主键,避免UPDATE/DELETE导致数据不一致。冲突解决策略可借助外部工具如Bucardo或pglogical实现更细粒度的冲突解决规则。
复制监控与性能调优
逻辑复制性能受WAL生成速率、网络带宽、订阅端应用速度影响。关键监控指标:
-- 复制延迟(字节)
SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes
FROM pg_replication_slots WHERE slot_name = 'sub_users_slot';
-- 复制延迟(时间,需pg_stat_statements扩展)
SELECT now() - pg_last_xact_replay_timestamp() AS replication_lag;
-- 订阅端apply延迟
SELECT * FROM pg_stat_subscription
WHERE subname = 'sub_users';
调优方向:增大max_logical_replication_workers提升并行应用能力;调整logical_decoding_work_mem控制解码内存;对大表初始同步使用pg_dump+pg_restore代替copy_data,减少复制槽WAL堆积。生产环境建议配合Patroni或repmgr实现自动故障切换,保证复制拓扑的高可用性。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/postgresql-luo-ji-fu-zhi-pei-zhi-yu-duo-huo-jia-gou-shu-ju/