实现零手工同步:Spock 自动 DDL 复制配置实战教程(完整指南)
【免费下载链接】spockLogical multi-master PostgreSQL replication项目地址: https://gitcode.com/gh_mirrors/spock3/spock
在 PostgreSQL 多主复制场景中,最耗费运维精力的往往不是数据本身,而是表结构变更。每当开发环境执行一条ALTER TABLE,你都要在集群的每个节点上手工重放一遍,稍有不慎就会造成主备结构漂移。Spock 自动 DDL 复制正是为解决这一痛点而生:它是逻辑多主复制扩展 Spock 提供的核心能力,能够在集群节点间自动同步建表、加列、改索引等 DDL 语句,让数据库结构变更像普通数据一样"零手工"复制,从源头杜绝结构不一致引发的复制故障。本文将为你带来一份面向新手的完整配置实战教程。
为什么你需要 Spock 自动 DDL 复制?
传统 PostgreSQL 逻辑复制(Publication/Subscription)只复制 DML 数据变更,不复制 DDL。这意味着:
- 每次加列、建索引都要在所有节点手工执行
- 一旦遗漏某个节点,复制进程会报 "column does not exist" 错误
- 多节点集群中,结构变更顺序难以保证
Spock 作为逻辑多主复制扩展,内置了 DDL 自动捕获与分发机制。开启后,你在任意节点执行的 DDL 会通过复制通道广播到所有订阅节点,真正做到"一次变更,处处生效"。🎯
前置条件:先搭好双节点复制集群
自动 DDL 复制依赖一个已正常工作的 Spock 复制集群。如果你是第一次接触 Spock,建议先按以下步骤完成基础搭建(详细步骤见官方文档docs/getting_started.md):
- 安装 Spock 扩展(RPM/DEB 包或源码编译,源码位于
src/spock_autoddl.c) - 在
postgresql.conf中配置wal_level = logical、shared_preload_libraries = 'spock' - 在两个节点分别执行
CREATE EXTENSION spock - 创建节点定义并建立双向订阅(
spock.node_create、spock.sub_create)
一键开启:核心配置参数详解
Spock 通过 4 个 GUC 参数控制 DDL 复制行为。你只需在两台节点上分别执行下面这段配置即可开启核心功能(来自docs/getting_started.md的推荐配置):
ALTER SYSTEM SET spock.enable_ddl_replication = on; ALTER SYSTEM SET spock.include_ddl_repset = on; SELECT pg_reload_conf();这段命令同时开启了两大能力:
| 参数 | 作用 | 典型场景 |
|---|---|---|
spock.enable_ddl_replication | 通过默认复制集自动复制 DDL 语句 | 建表、加列、改索引全自动同步 |
spock.include_ddl_repset | 新表创建时自动加入复制集 | 有主键表进default,无主键表进default_insert_only |
spock.allow_ddl_from_functions | 复制函数内部执行的 DDL | 存储过程动态建表 |
spock.deny_all_ddl | 完全阻止所有 DDL 执行 | 维护窗口、节点修复期的安全护栏 |
细节一:函数里的 DDL 也能自动复制
业务中常有存储过程动态建表的需求。开启spock.allow_ddl_from_functions = on后,函数内执行的CREATE TABLE也会被自动捕获并复制。如果这些函数本来就会在每个节点手动执行,可以保持关闭,避免重复执行报错。
细节二:分区表与主键变更的智能处理
include_ddl_repset会在建表瞬间自动完成复制集注册:
- 有主键的表 → 自动加入
default复制集 - 无主键的表 → 自动加入
default_insert_only复制集 - 后续
ALTER TABLE增删主键 → 自动切换所属复制集 - 表被设置为
unlogged→ 自动移出复制
细节三:deny_all_ddl 紧急制动
在敏感维护窗口或节点修复期间,可临时执行:
ALTER SYSTEM SET spock.deny_all_ddl = on;开启后 Spock 会拒绝该节点上的所有 DDL 语句(超级用户可随时运行时切换,无需重启),为你的集群加一道"只读锁"。🔒
手动复制:spock.replicate_ddl() 函数兜底
如果你不想全局开启自动 DDL 复制,只想偶尔同步某条 DDL,Spock 提供了精确的手动入口。执行SELECT spock.replicate_ddl(...)即可在本地执行 DDL 的同时将其排入复制队列(详见docs/spock_functions/functions/spock_replicate_ddl.md):
-- 创建表并同步到订阅节点 SELECT spock.replicate_ddl('CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)'); -- 批量同步多条 DDL SELECT spock.replicate_ddl(ARRAY['CREATE TABLE orders (id SERIAL)', 'CREATE INDEX ON orders(id)']);函数支持指定replication_sets(默认{ddl_sql})、search_path和role参数,粒度控制非常灵活。
实战验证:三步确认 DDL 已自动同步
配置完成后,用最简单的方式验证效果:
第 1 步:在节点 n1 执行建表 + 插入数据:
CREATE TABLE test (id SERIAL PRIMARY KEY, message TEXT); INSERT INTO test (message) VALUES ('Hello from n1');第 2 步:在节点 n2 直接查询,无需任何手工操作:
SELECT * FROM test; -- 应能看到表结构 + n1 插入的数据第 3 步:反向测试。在 n2 执行ALTER TABLE test ADD COLUMN email TEXT,回到 n1 用\d test检查——新列应该已经出现。
如果一切顺利,你就拥有了一个"改一次、处处同步"的双主集群。🎉
最佳实践与注意事项
✅何时开启:所有节点 schema 完全一致(要么全空、要么完全相同且表都在复制集中)时开启最安全。
⚠️两类 DDL 不会复制:
CREATE DATABASE等语句被有意排除- 涉及临时表的
CREATE TABLE ... AS会先复制 DDL 再建表,可能造成数据不一致,日志会给出DDL statement replicated, but could be unsafe.警告
📌日志观察:设置log_min_messages=INFO后,成功复制的 DDL 会输出DDL statement replicated.信息,排查问题非常方便。
🔁复制集注意:DROP TABLE在多节点集群中可能引发连锁问题,生产环境建议结合复制集权限谨慎使用。
总结
Spock 自动 DDL 复制把多主集群中最繁琐的结构同步工作变成了"零手工"操作。核心只需记住三件事:开启enable_ddl_replication和include_ddl_repset两个参数、用replicate_ddl()做精细兜底、用deny_all_ddl做紧急制动。配置一次,永久受益,从此告别逐节点手工跑 DDL 的日子。想深入了解参数细节,可查阅官方文档docs/configuring.md与docs/managing/spock_autoddl.md,或直接阅读源码src/spock_autoddl.c理解其实现机制。
【免费下载链接】spockLogical multi-master PostgreSQL replication项目地址: https://gitcode.com/gh_mirrors/spock3/spock
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考