18.3. 模板数据库

CREATE DATABASE 实际上是通过拷贝一个现有的数据库进行工作的。 缺省时,它拷贝名字叫 template1 的标准系统数据库。 所以该数据库是创建新数据库的"模板"。如果你给 template1 增加对象,这些对象将被拷贝到随后创建的用户数据库中。 这样的行为允许节点对数据库中的标准套件进行修改。 比如,如果你把过程语言 PL/pgSQL 安装到 template1 里,那么你在创建用户数据库的时候它们就会自动可得,而不需要额外的动作。

系统里还有第二个标准的系统数据库,叫 template0。 这个数据库包含和 template1 一开始时一样的数据内容, 也就是说,只有你使用的版本的 PostgreSQL 标准的对象。在 initdb 之后,我们不应该对 template0 做任何修改。通过告诉 CREATE DATABASE 使用 template0 而不是 template1 进行拷贝, 你可以创建一个"纯净"的用户数据库,它不会包含任何 template1 里节点所特有的东西。 这一点在恢复 pg_dump 转储的时候是非常方便的: 转储脚本应该在一个纯洁的数据库中恢复以确保我们创建了被转储出的数据库中的正确内容, 而不和任何现在可能已经存在在 template1 中的附加物相冲突。

要通过拷贝 template0 的方法创建一个数据库, 使用

CREATE DATABASE dbname TEMPLATE template0;

这条命令是在 SQL 环境里的,或者是在 shell 里

createdb -T template0 dbname

我们可以创建额外的模板数据库,而且实际上我们可以在一个集群中通过将 CREATE DATABASE 的模板声明为相应的数据库名拷贝任何数据库。 不过,我们必需明白,这个功能并非一般性的"COPY DATABASE"工具。 实际上,在拷贝操作的过程中,源数据库必需是空闲状态(没有正在处理的数据修改事务)。 CREATE DATABASE 在操作开始时将会检查确保没有会话(除它自己以外)与源数据库联接, 但是这样并不能保证在拷贝过程中不会发生修改的事情,如果发生这些事情,那么会导致一个不一致的结果数据库。 因此,我们建议那些用做模板的数据库应该当做只读库对待。

pg_database 里有两个有用的标志可以用于每个数据库: 字段 datistemplatedatallowconndatistemplate 表示该数据库是准备用做 CREATE DATABASE 的模板的。 如果设置了这个标志,那么该数据库可以由任何有 CREATEDB 权限的用户克隆;如果没有设置,那么只有超级用户和该数据库的所有者可以克隆它。 如果 datallowconn 为假,那么将不允许与该数据库发生任何新的连接(不过现有的会话不会因为把该标志设置为假而被杀死)。 template0 数据库通常被标记为 datallowconn = false 以避免对它的修改。 template0template1都应该总是标记为datistemplate = true

完成模板数据库的准备之后,或者对某个数据库做了任何标记修改之后, 在该数据库中执行一次 VACUUM FREEZE 是一个好主意。 如果做这些的时候在同一个数据库中没有其它打开的事务,那么系统保证在数据库中的行是"冻结"的, 并且不会受事务 ID 重叠的影响。这个动作对那些 datallowconn 设置为假的数据库特别重要, 因为在这样的数据库上没有办法做日常维护性的VACUUM。 参阅 Section 21.1.3 获取更多信息。

注意: template1template0 没有任何特殊的状态, 除了 template1 这个名字是 CREATE DATABASE 以及各种象 createdb 这样的程序的缺省源数据库名之外。 比如,我们可以删除 template1,然后从 template0 中创建它而不会有任何不良效果。如果我们不小心在 template1 里加了一堆垃圾,那么我们就会建议做这样的操作。