微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

PostgreSQL创建数据库时报错:ERROR: source database "template1" is being accessed by other users

删除表时,表被锁住,只要选中这个表,整个navicat就没了响应。

最暴力的解决办法是重启Postgresql服务,但今天是在正式环境玩,这样可不行!


最终是删除库,然后建库

CREATE DATABASE appupdate4
WITH OWNER = postgres template=template0
ENCODING = 'UTF8'
TABLESPACE = pg_default
LC_COLLATE = 'Chinese (Simplified)_People''s Republic of China.936'
LC_CTYPE = 'Chinese (Simplified)_People''s Republic of China.936'
CONNECTION LIMIT = -1;

详解见:http://hi.baidu.com/11haIoU/item/1a86304b3c40f2c1c1a592bb


环境:

Postgresql服务器所在操作系统为:linux

客户端有两个,一个linux下的:psql

一个Windowsxp下的:NavicatPremium

发现问题:

psql中用“createdatabase$数据库名称;”创建数据库时,发现报错:

ERROR:sourcedatabase"template1"isbeingaccessedbyotherusers

DETAIL:Thereis1othersessionusingthedatabase.

详细见下图:

分析问题:

错误信息可以看出,模板数据库template1正在被其他用户访问,所以不能在创建数据库时以它为模版进行创建,后台通过“ps-ef|greppostg”,见下图:

从上图可以看出,模板数据库template1”正在被客户端“192.168.20.1041666)”访问。这里,需要明白三个问题:

一是,在创建数据库时为什么跟模板数据库template1扯上了关系?

二是,postmasterpostgres进程之间的关系?

三是:“192.168.20.1041666)”是谁?

先看第一个,原来Postgresql在用initdb创建数据库集群时,将创建一个模板数据库template1,以后所有的数据库都将来源于模板数据库template1,其中也包括模板数据库template0.

换句话说,template1templat0用于创建数据库,即Postgresql中用从模板数据库复制的方式创建一个新的数据库,而template1就是创建数据库认模板。

所以如果用户在创建数据库时不为数据库指定模板,那么将使用template1模板数据库。这便是对问题一的回答,下面来看第二个问题“postmasterpostgres进程之间的关系?”。

原来,postmaster是运行在服务器上的主进程(也称监听守护进程),而postgrespostmaster的子进程,这一点从上图中进行号也可以看出来(27113postmaster的进程号,而27122postmaster子进程之一),那么postmaster主进程在什么情况下将开启一个子进程呢?

首先,客户端想访问服务器中某数据库,客户端将调用接口库(如ODBClibpq等)将用户的请求通过网络发送给主进程postmaster

接着,当postmaster接收到客户端发送过来的用户请求后,它将启动一个新的后端进程postgres用户服务,此后,postmaster就将与客户端的交互工作交由postgres服务进程,而有postgres来完成客户端所需要的各种操作。

说完postmasterpostgres进程之间的关系,再来看看“192.168.20.1041666)”究竟是谁?

Windowsxpdos窗口中,用“ipconfig”查看到的地址是就是“192.168.20.104”,详见下图:

NavicatPremium客户端连接Postgresql服务器,连接配置如下图:

看到初始数据库为:template1,一旦用户创建好连接并连接上之后,postmaster主进程就会为客户端192.168.20.104启动一个postgres服务进程(postgres:postgrestemplate1192.168.20.104(2168)idle)用于与客户端进行交互。

注意:

1.IP地址后括弧中的数字为端口(随机分配一个未用的)

2.初始数据库不一定非要为模板数据库template1,可以任意指定一个已存在于Postgresql服务器中的数据库

解决问题:

通过以上分析,其实要解决这几个问题有以下几种方案:

1.Linux中重启Postgresql服务器进程(/etc/rc.d/init.d/postgresqlrestart)后,再在psql中用“createdatabase$数据库名称;”创建数据库。注:不推荐使用这一方案。

2.关闭Windowsxp下的NavicatPremium客户端关于连接到Postgresql服务器的连接,然后再在psql中用“createdatabase$数据库名称;”创建数据库。见下图:

3.linux服务器中用“kill-9$进程号”杀死Postgresql服务进程(本例中的进程号为27122),然后再在psql中用“createdatabase$数据库名称;”创建数据库

4.在创建数据库时指定模板数据库template0,指定方式在psql客户端中用“createdatabase$数据库名称withtemplate=template0;”(中的with可有可无),在shell命令行(请先切换到postgres用户)中用“createdb$数据库名称-Ttemplate0”或“createdb$数据库名称--template=template0”均可,“-T--template”含义见下图:




另在网上看到这样一句:(没试过,慎用!

VACUUM 
回收已删除元组占据的存储空间。 在一般的 Postgresql 操作里, 那些已经 DELETE 的元组或者被 UPDATE 
过后过时的元组是没有从它们所属的表中物理删除的; 在完成 VACUUM 之前它们仍然存在。 因此我们有必须周期地运行 VACUUM, 
特别是在常更新的表上,如果没有参数,VACUUM 处理当前数据库里每个表, 如果有参数,VACUUM 只处理那个表,简单的 VACUUM (没有FULL) 
只是简单地回收空间并且令其可以再次使用;

原文地址:https://www.jb51.cc/postgresql/195761.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐