【PostgreSQL的模板库存在连接导致创建数据库失败】

众所周知,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.

二、解决

解决的方法其实要么使用另外一个没有连接的模板库,或者是断开该模板库上的连接。

1.使用额外的模板库

如下所示,使用额外的模板库则可以创建成功。

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

2.断开该模板库上的连接

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

三、附:访问template0模板库(不建议更改,单纯演示)

当我们正常去连接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的模板数据库 - 墨天轮

你可能感兴趣的:(PostgreSQL,数据库,postgresql)