Skip to content

逻辑复制 ​

核心问题:逻辑复制和流复制有什么区别?如何实现选择性复制?如何用于数据迁移?

1. 逻辑复制 vs 流复制 ​

对比项流复制逻辑复制
复制粒度整个集群特定表
复制内容WAL 字节级复制逻辑行级变更
版本兼容必须同版本支持跨版本
用途高可用、读写分离数据迁移、数据分发、部分同步

2. 发布端配置 ​

ini
# postgresql.conf
wal_level = logical
sql
-- 创建发布
CREATE PUBLICATION my_pub FOR TABLE users, orders;
-- 或发布所有表
CREATE PUBLICATION my_pub FOR ALL TABLES;

3. 订阅端配置 ​

sql
-- 创建订阅
CREATE SUBSCRIPTION my_sub
    CONNECTION 'host=192.168.1.100 dbname=mydb user=replicator password=secret'
    PUBLICATION my_pub;

4. 选择性复制 ​

sql
-- 只发布特定表
CREATE PUBLICATION user_pub FOR TABLE users, user_profiles;

-- 发布特定操作
CREATE PUBLICATION insert_only FOR TABLE audit_logs
    WITH (publish = 'insert');

-- 启用 TRUNCATE 复制(PG 14+)
CREATE PUBLICATION my_pub FOR ALL TABLES
    WITH (publish = 'insert, update, delete, truncate');

-- 修改发布
ALTER PUBLICATION user_pub ADD TABLE orders;
ALTER PUBLICATION user_pub DROP TABLE user_profiles;

5. 监控复制状态 ​

sql
-- 查看订阅状态
SELECT
    subname, worker_type,
    last_msg_send_time, last_msg_receipt_time,
    latest_end_lsn, last_xact_replay_lag
FROM pg_stat_subscription;

-- 查看复制槽
SELECT
    slot_name, plugin, slot_type, active,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag
FROM pg_replication_slots;

6. 逻辑复制的限制 ​

限制说明
DDL 不复制表结构变更需要手动在订阅端执行
序列不复制SEQUENCE 的值不会自动同步
TRUNCATE 不复制默认不复制 TRUNCATE 操作
需要主键默认需要表有主键(或 REPLICA IDENTITY)
sql
-- 设置 REPLICA IDENTITY(无主键表)
ALTER TABLE logs REPLICA IDENTITY FULL;

7. 逻辑复制用于数据迁移 ​

sql
-- 场景:从 PG 14 迁移到 PG 16
-- 1. 在 PG 16 上创建相同的表结构
-- 2. 在 PG 14 上创建发布
CREATE PUBLICATION migration_pub FOR ALL TABLES;

-- 3. 在 PG 16 上创建订阅
CREATE SUBSCRIPTION migration_sub
    CONNECTION 'host=pg14_host dbname=mydb user=replicator password=secret'
    PUBLICATION migration_pub
    WITH (copy_data = true);

-- 4. 等待数据同步完成
SELECT * FROM pg_stat_subscription;

-- 5. 切换应用到 PG 16
-- 6. 删除订阅和发布
DROP SUBSCRIPTION migration_sub;
DROP PUBLICATION migration_pub;

重要:逻辑复制槽如果不活跃,会导致 WAL 文件不断堆积,最终磁盘满。务必监控复制槽状态,及时清理不活跃的复制槽。

Released under the MIT License.