众所周知,PostgreSQL里包含两个标准系统数据库,template0和template1。
创建数据库时,CREATE DATABASE通过拷贝一个已有数据库进行工作。默认情况下,它拷贝名为template1的标准系统数据库,这个template1其实可以根据我我们的需求去做部分调整,使之后以它为模板库CREATE DATABASE的时候,都能带上相同的对象。但是CREATE DATABASE的时候,模板库是不允许存在连接的。
而template0模板库默认是不允许访问的(其实也可以通过update pg_database的datallowconn列允许连接,但是不建议这么做),而且在数据库被初始化之后,不应该对template0做任何修改,可以在复制template0时指定新的编码和区域设置,但是template1的副本必须使用和它相同的设置。这是因为的template1可能包含编码相关或区域相关的数据,而template0中没有。
如下给大家模拟下,当执行CREATE DATABASE命令,而需要作为模板库的库存在连接的时候,数据库创建失败的场景。
首先使用一个session1,连接到template1的模板数据库里
session:1
[xmaster@mogdb-kernel-0005 ~]$ psql -d template1
psql (14.1)
Type "help" for help.
template1=# select pg_backend_pid();
pg_backend_pid
----------------
338659
(1 row)
template1=# select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend';
datname | pid | usename | query | backend_type
-----------+--------+---------+----------------------------------------------------------------------------------------------------------+----------------
template1 | 338659 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
(1 row)
然后使用另一个session2,连接到默认的postgres数据库里,创建一个新的数据库,未指定模板库的情况下,它是默认以template1为模板库的,template1的库已经被连接占上了,因此出现了如下的错误。
session:2
[xmaster@mogdb-kernel-0005 ~]$ psql
psql (14.1)
Type "help" for help.
postgres=# select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend';
datname | pid | usename | query | backend_type
-----------+--------+---------+----------------------------------------------------------------------------------------------------------+----------------
postgres | 338881 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
template1 | 338659 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
(2 rows)
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+---------+----------+-------------+-------------+---------------------
pg14 | xmaster | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
postgres | xmaster | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | xmaster | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/xmaster +
| | | | | xmaster=CTc/xmaster
template1 | xmaster | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/xmaster +
| | | | | xmaster=CTc/xmaster
(4 rows)
postgres=# create database l1;
ERROR: source database "template1" is being accessed by other users
DETAIL: There is 1 other session using the database.
解决的方法其实要么使用另外一个没有连接的模板库,或者是断开该模板库上的连接。
如下所示,使用额外的模板库则可以创建成功。
postgres=# select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend';
datname | pid | usename | query | backend_type
-----------+--------+---------+----------------------------------------------------------------------------------------------------------+----------------
postgres | 338881 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
template1 | 338659 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
(2 rows)
postgres=# create database l1;
ERROR: source database "template1" is being accessed by other users
DETAIL: There is 1 other session using the database.
postgres=# create database l1 TEMPLATE template0;
CREATE DATABASE
postgres=# select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend';
datname | pid | usename | query | backend_type
-----------+--------+---------+----------------------------------------------------------------------------------------------------------+----------------
postgres | 338881 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
template1 | 338659 | xmaster | | client backend
(2 rows)
postgres=# create database l1;
ERROR: source database "template1" is being accessed by other users
DETAIL: There is 1 other session using the database.
postgres=# select pg_terminate_backend(338659);
pg_terminate_backend
----------------------
t
(1 row)
postgres=# select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend';
datname | pid | usename | query | backend_type
----------+--------+---------+----------------------------------------------------------------------------------------------------------+----------------
postgres | 338881 | xmaster | select datname,pid,usename,query,backend_type from pg_stat_activity where backend_type='client backend'; | client backend
(1 row)
postgres=# create database l1;
CREATE DATABASE
当我们正常去连接template模板库的时候,是连接不上的,会有如下提示
[xmaster@mogdb-kernel-0005 ~]$ psql -d template0
psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL: database "template0" is not currently accepting connections
这个时候,我们去update pg_database这个系统表,把datallowconn给他变为t,则重试一下就可以连接进template0模板库了。
[xmaster@mogdb-kernel-0005 ~]$ psql
psql (14.1)
Type "help" for help.
postgres=# select oid,datname,datistemplate,datallowconn,datconnlimit from pg_database;
oid | datname | datistemplate | datallowconn | datconnlimit
-------+-----------+---------------+--------------+--------------
13023 | postgres | f | t | -1
16384 | pg14 | f | t | -1
1 | template1 | t | t | -1
34789 | l1 | f | t | -1
13022 | template0 | t | f | -1
(5 rows)
postgres=# update pg_database set datallowconn='t' where datname='template0';
UPDATE 1
postgres=# select oid,datname,datistemplate,datallowconn,datconnlimit from pg_database;
oid | datname | datistemplate | datallowconn | datconnlimit
-------+-----------+---------------+--------------+--------------
13023 | postgres | f | t | -1
16384 | pg14 | f | t | -1
1 | template1 | t | t | -1
34789 | l1 | f | t | -1
13022 | template0 | t | t | -1
(5 rows)
postgres=# \q
[xmaster@mogdb-kernel-0005 ~]$ psql -d template0
psql (14.1)
Type "help" for help.
template0=#
记得把template0的这个datallowconn='f’修改回来!
PostgreSQL的模板库的内容也可以参考我另一篇文章:[]PostgreSQL的模板数据库 - 墨天轮