🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 21.3\. 模板数据库 `CREATE DATABASE`实际上是通过拷贝一个现有的数据库进行工作的。缺省时, 它拷贝名为`template1`的标准系统数据库。 所以该数据库是创建新数据库的"模板"。如果你给`template1`增加对象, 这些对象将被拷贝到随后创建的用户数据库中。这样的行为允许节点对数据库中的标准套件进行修改。 比如,如果你把过程语言PL/Perl安装到`template1`里, 那么你在创建用户数据库的时候它们就会自动可得,而不需要额外的动作。 系统里还有名为`template0`的第二个标准系统数据库, 这个数据库包含和`template1`初始时一样的数据内容,也就是说, 只包含标准的PostgreSQL对象。在数据库集群初始化之后, 我们不应该对`template0`做任何修改。通过告诉`CREATE DATABASE`使用 `template0`而不是`template1`进行拷贝,你可以创建一个"纯净" 的用户数据库,它不会包含任何`template1`里所特有的东西。 这一点在恢复`pg_dump`转储的时候是非常方便的: 转储脚本应该在一个纯净的数据库中恢复以确保我们正确创建了被转储出的数据库内容, 而不会随后和可能已经添加到`template1`中的对象相冲突。 拷贝`template0`而不是`template1`的另一个常见原因是在拷贝 `template0`时,可以指定新的编码和本地设置,而拷贝`template1` 时必须使用和`template1`相同的设置。这是因为`template1` 可能包含编码指定或本地指定的数据,而`template0`不这样。 要通过拷贝`template0`的方法创建一个数据库,可使用: ``` CREATE DATABASE _dbname_ TEMPLATE template0; ``` 用于 SQL 环境,或: ``` createdb -T template0 _dbname_ ``` 用于 shell 环境。 我们可以创建额外的模板数据库,而且实际上我们可以在一个集群中通过将 `CREATE DATABASE`的模板声明为相应的数据库名拷贝任何数据库。不过, 我们必需明白,这个功能并非一般性的"`COPY DATABASE`"工具。 实际上,在拷贝操作的过程中,源数据库必需是空闲状态(没有正在处理的数据修改事务)。 如果在`CREATE DATABASE`开始的时候存在其它连接,那么操作将会失败, 在拷贝期间,到源数据库的新连接都被阻止。 在`pg_database`里有两个有用的标志可以用于每个数据库: `datistemplate`和`datallowconn`字段。`datistemplate` 表示该数据库是准备用作`CREATE DATABASE`模板的。如果设置了这个标志, 那么该数据库可以由任何有`CREATEDB`权限的用户克隆;如果没有设置, 那么只有超级用户和该数据库的所有者可以克隆它。如果`datallowconn`为假, 那么将不允许与该数据库发生任何新的连接(不过现有的会话不会因为把该标志设置为假而终止)。 `template0`数据库通常被标记为`datallowconn = false`以避免对它的修改。 `template0`和`template1`都应该总是标记为`datistemplate = true`。 > **Note:** `template1`和`template0`没有任何特殊的状态, 除了`template1`是`CREATE DATABASE`的缺省源数据库名之外。比如, 我们可以删除`template1`然后从`template0`中创建它而不会有任何不良效果。 如果我们不小心在`template1`里加了一堆垃圾,那么我们就会建议做这样的操作。 (要删除`template1`,必须使`pg_database.datistemplate = false`。) > > 在初始化数据库集群的时候,也会创建`postgres`数据库。 这个数据库用于做为用户和应用连接的缺省数据库。它只是`template1`的一个简单拷贝, 需要的时候可以删除或者重建。