- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
PostgreSQL 提供了一条足以"秒杀" dump/restore 的本地数据库复制路径:createdb -T模板复制。本指南以 til 仓库中的 duplicate-a-local-database 笔记为骨架,讲解如何在不导出、不导入任何数据文件的情况下,通过模板机制瞬间克隆出包含完整 schema 与数据的全新数据库,并深入其底层原理(template0/template1)、所有者指定技巧以及与pg_dump方案的取舍。读完你就能用一条命令完成本地库复制,并知道何时该改用 dump/restore。
一条命令完成本地数据库复制
当源数据库就在本机、且没有跨服务器或跨版本迁移需求时,完全不需要经历"dump → 新建空库 → restore"三步。PostgreSQL 自带的createdb命令内置了基于模板的复制能力:
$ createdb -O ownername -T originaldb newdb命令执行后,PostgreSQL 会在当前集群内创建一个名为newdb的新数据库,其 schema 与数据全部来自originaldb。整个操作在服务端完成,数据无需经过客户端中转,因此对大库也几乎只受磁盘 I/O 限制。
参数含义拆解:
-T originaldb(--template):指定以哪个数据库作为模板。这是本命令的核心,PostgreSQL 会完整复制该库的 schema 和数据到新库。-O ownername(--owner):指定新数据库的所有者(owner),不传则默认使用执行命令的操作系统用户。newdb:要创建的新数据库名称(位置参数)。
原理:一切数据库都诞生自模板
这条命令之所以成立,是因为 PostgreSQL 的CREATE DATABASE本质上就是"从模板克隆"。正如 til 仓库中的 create-database-uses-template1 笔记所记录的:每次create database(除非显式指定),PostgreSQL 默认都会克隆template1。
每个 PostgreSQL 集群启动时都自带两个模板库,可通过以下查询验证:
select datname from pg_database where datistemplate = true; datname ----------- template1 template0 (2 rows)- template1:默认模板,
createdb newdb不指定-T时实际上克隆的就是它。可以对它执行\c template1连接并修改——比如把某个扩展、函数或公共 schema 放进去,之后创建的每一个新库都会自动继承。 - template0:
template1的原始备份副本,无法连接、无法修改,专用于在 template1 被改坏时作为恢复兜底。
所以createdb -T originaldb newdb只是把默认的template1换成了你自己的库:克隆逻辑完全一致,区别只在于模板来源。当你不希望新库继承 template1 中的自定义内容时,也可以显式用-T template0创建"干净"的库。
-O:把新库交给正确的所有者
-O直接对应 SQL 语法中的CREATE DATABASE ... OWNER ...。在本地开发场景,新库的所有者通常应设为当前 Unix 用户,这样你现有的本地角色才能顺畅读写新库;如果复制出来的库所有者是他人角色,本地连接时很可能遇到权限不足的问题。
如果需要先确认目标角色是否存在(比如自动化脚本里先查后建),til 仓库的 check-if-user-role-exists-for-database 笔记给出了可脚本化的写法:
psql postgres -tXAc "SELECT 1 FROM pg_roles WHERE rolname='dev'" \ | grep -q 1 \ || createuser --interactive devcreatedb与createuser同属 PostgreSQL 客户端工具族,配合使用即可在复制数据库前把角色体系准备妥当。
模板复制 vs. pg_dump:如何选
模板复制并非万能,它与 dump-and-restore-a-database 笔记中的pg_dump/pg_restore方案各有适用场景:
| 维度 | createdb -T模板复制 | pg_dump -Fc+pg_restore |
|---|---|---|
| 适用场景 | 源库与目标库同机、同集群 | 跨服务器、跨版本、需归档备份 |
| 数据通道 | 服务端文件系统级拷贝,不经客户端 | 数据序列化到 dump 文件再反序列化 |
| 额外产物 | 无 | 产生.dump文件 |
| 典型命令 | createdb -O owner -T src dst | pg_dump -Fc my_db > my_db.dump后createdb my_new_db && pg_restore -d my_new_db my_db.dump |
| 角色依赖 | 源库内角色信息随模板保留 | restore 时需保证依赖角色已存在于目标集群 |
需要重点指出的是:pg_dump的 dump 文件本身不包含角色定义,恢复时若目标集群缺少相应角色会失败,需要先用createuser补齐;而模板复制发生在同一集群内,角色体系天然一致,无需额外处理。
另外,当源库正被活跃连接占用时,PostgreSQL 会拒绝以它作为模板创建新库(模板克隆要求源库处于空闲一致状态)。因此复制前请确保源库没有进行中的写入会话;若确需拷贝"正在使用"的库,则应退回到pg_dump方案,它通过一致性快照读取数据,不受活动连接影响。
复制结果的独立性与其他实操提示
- 复制出的新库完全独立:
newdb与originaldb只是"长相一致"的两个库,后续对任一方的修改互不影响,模板关系仅存在于创建瞬间,不会形成持续同步。 - 复制不带走连接级设置:当前会话的临时配置(如
search_path的会话级修改)不会进入新库,新库继承的是源库中持久化的对象定义与数据。 - 查看复制结果:用
psql的\l+元命令即可列出所有数据库及其大小,验证newdb是否如期出现;也可参考 check-the-size-of-databases-in-a-cluster 笔记中的 SQL 查询来核对体积。 - 集群整体迁移仍需 pg_dumpall:如果目标是重装 PostgreSQL、整体搬迁整个集群(含角色、权限),模板复制无法胜任,应改用 dump-all-databases-to-a-sql-file 笔记中的
pg_dumpall,并通过--exclude-database="template*"排除随安装自带的模板库。
小结
createdb -O ownername -T originaldb newdb是本地 PostgreSQL 开发中最高效的"复制库"手段:它借力模板克隆机制,在服务端一步完成 schema 与数据的全量复制,省去了 dump/restore 的序列化开销与中间文件。理解 template0/template1 的分工、正确设置-O所有者、并清楚它与pg_dump的边界,就能在任何"想要一个一模一样的新库"的场景下做出正确选择——同机克隆用-T,跨机迁移用 dump/restore。
- 文档
- 教程
- 知识库
【免费下载链接】til
:memo: Today I Learned
相关推荐
TIL 实战:用 pg_database_size() 获取 PostgreSQL 数据库磁盘占用
TIL 实战:用 pg_database_size 获取 PostgreSQL 数据库磁盘占用 在 PostgreSQL 日常运维中,快速获知某个数据库到底占用
文档教程知识库PostgreSQL 模板数据库机制:CREATE DATABASE 为何默认克隆 template1
PostgreSQL 模板数据库机制:CREATE DATABASE 为何默认克隆 template1 导读 在 PostgreSQL 中执行 CREATE D
文档教程知识库终极PostgreSQL数据复制实战:pg_replicate完全指南
终极PostgreSQL数据复制实战:pg_replicate完全指南 pg_replicate是一个基于Rust构建的PostgreSQL数据复制工具,它利用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考