杀死一个PostgreSQL会话/连接


369

如何杀死我所有的Postgresql连接?

我正在尝试a rake db:drop但我得到:

ERROR:  database "database_name" is being accessed by other users
DETAIL:  There are 1 other session(s) using the database.

我尝试关闭从a看到的进程,ps -ef | grep postgres但这也不起作用:

kill: kill 2358 failed: operation not permitted

当所有其他尝试均失败时,pgreset gem会以某种方式固定rails / pg并认为存在连接,但实际上并没有。
JosephK

Answers:


671

您可以使用pg_terminate_backend()终止连接。您必须是超级用户才能使用此功能。这在所有操作系统上均相同。

SELECT 
    pg_terminate_backend(pid) 
FROM 
    pg_stat_activity 
WHERE 
    -- don't kill my own connection!
    pid <> pg_backend_pid()
    -- don't kill the connections to other databases
    AND datname = 'database_name'
    ;

在执行此查询之前,您必须撤销 CONNECT特权以避免建立新连接:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

如果您使用的是Postgres 8.4-9.1,请使用procpid而不是pid

SELECT 
    pg_terminate_backend(procpid) 
FROM 
    pg_stat_activity 
WHERE 
    -- don't kill my own connection!
    procpid <> pg_backend_pid()
    -- don't kill the connections to other databases
    AND datname = 'database_name'
    ;

68
请注意,在Postgres 9.2中,procpid重命名为pid。
Devin 2012年

如果他是超级用户,他还是不能sudo杀人吗?
ndnenkov '16

3
@ndn数据库超级用户与操作系统级别超级用户不是同一个人。sudoPG中没有。
jpmc26 2016年

这是许多SO问题的唯一可行答案,因为它具有REVOKE步骤性。您还救了一个人,我猜又是一次!
AymDev

这个作品感谢....
阿贾伊·库马尔


28

关于运行过程的所有信息:

SELECT *, pg_terminate_backend(pid)
FROM pg_stat_activity 
WHERE pid <> pg_backend_pid()
AND datname = 'my_database_name';


13

OSX,Postgres 9.2(与自制软件一起安装)

$ launchctl unload -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist
$ pg_ctl restart -D /usr/local/var/postgres
$ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist


如果您的datadir在其他位置,则可以通过检查以下命令的输出来找出它的位置 ps aux | grep postgres


4
brew services restart postgresql
PJSCopeland

@PJSCopeland感谢您提供最简单的解决方案!我认为您的评论应该是一个真实的答案,因此:stackoverflow.com/a/48226667/1097104
Juuso Ohtonen

谢谢你,@ JuusoOhtonen。告诉您什么,但是,如果您希望从中获得声誉,则可以至少链接回我的评论?
PJSCopeland

@PJSCopeland完成。
Juuso Ohtonen

其他答案和其他类似的SO post解决方案有问题。运行您pg_ctl restart -D /usr/local/var/postgres的技巧!(我什至没有运行第一个或第三个命令)。
Iggy

8

这似乎适用于PostgreSQL 9.1:

#{Rails.root}/lib/tasks/databases.rake
# monkey patch ActiveRecord to avoid There are n other session(s) using the database.
def drop_database(config)
  case config['adapter']
  when /mysql/
    ActiveRecord::Base.establish_connection(config)
    ActiveRecord::Base.connection.drop_database config['database']
  when /sqlite/
    require 'pathname'
    path = Pathname.new(config['database'])
    file = path.absolute? ? path.to_s : File.join(Rails.root, path)

    FileUtils.rm(file)
  when /postgresql/
    ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
    ActiveRecord::Base.connection.select_all("select * from pg_stat_activity order by procpid;").each do |x|
      if config['database'] == x['datname'] && x['current_query'] =~ /<IDLE>/
        ActiveRecord::Base.connection.execute("select pg_terminate_backend(#{x['procpid']})")
      end
    end
    ActiveRecord::Base.connection.drop_database config['database']
  end
end

这里这里发现的要点中解除。

是适用于PostgreSQL 9.1和9.2 的修改版本


6

我使用以下rake任务来覆盖Rails drop_database方法。

lib/database.rake

require 'active_record/connection_adapters/postgresql_adapter'
module ActiveRecord
  module ConnectionAdapters
    class PostgreSQLAdapter < AbstractAdapter
      def drop_database(name)
        raise "Nah, I won't drop the production database" if Rails.env.production?
        execute <<-SQL
          UPDATE pg_catalog.pg_database
          SET datallowconn=false WHERE datname='#{name}'
        SQL

        execute <<-SQL
          SELECT pg_terminate_backend(pg_stat_activity.pid)
          FROM pg_stat_activity
          WHERE pg_stat_activity.datname = '#{name}';
        SQL
        execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
      end
    end
  end
end

编辑:这是为Postgresql 9.2 +


您需要使用pg_stat_activity.procpid代替pg_stat_activity.pidPostgres 9.1及更低版本。参见stackoverflow.com/a/5408501/444774
塔利里克

1
这是一个很好的答案!它比Rails默认更好,更安全。谢谢!
Piersadrian

5

更简单,更新的方式是:

  1. 使用ps -ef | grep postgres查找连接#
  2. sudo kill -9 "#" 连接的

注意:可能有相同的PID。杀死一个人会杀死所有人。


3

我遇到了这个问题,问题是Navicat已连接到本地Postgres数据库。一旦断开Navicat的连接,问题就消失了。

编辑:

另外,作为绝对的最后选择,您可以备份数据,然后运行以下命令:

sudo kill -15 `ps -u postgres -o pid`

...将会杀死postgres用户正在访问的所有内容。避免在生产机器上执行此操作,但是开发环境应该没有问题。重要的是,在此之后尝试重新启动PostgreSQL之前,确保每个 postgres进程都已真​​正终止。

编辑2:

由于这个unix.SE帖子,我已从更改kill -9kill -15


1
以我对Navicat Lite的有限经验,仅关闭数据库或服务器连接并不总是足够的。Navicat Lite似乎会保持偶尔的连接打开状态,直到应用程序终止。

3

我已经解决了这个问题:

在我的Windows8 64位系统中,只需restart执行以下服务:postgresql-x64-9.5


5
那只是执行通常对于生产环境而言不希望的重启,因此取消拥抱过程是一个更理想的选择。
BrianC

3
SELECT 
pg_terminate_backend(pid) 
FROM 
pg_stat_activity 
WHERE
pid <> pg_backend_pid()
-- no need to kill connections to other databases
AND datname = current_database();
-- use current_database by opening right query tool

1

只是想指出,如果其他某些后台进程正在使用数据库,Haris的答案可能无法正常工作,在我的情况下,这是延迟的工作,我这样做了:

script/delayed_job stop

直到那时,我才能够删除/重置数据库。


1

退出postgres并重新启动它。很简单,但是每次都对我有用,而其他cli命令有时却不行。


简单而有效!为了进一步澄清pgAdmin 4并重新启动
Ka Tech

0

无需删除它。只需删除并重新创建公共架构即可。在大多数情况下,这具有完全相同的效果。

namespace :db do

desc 'Clear the database'
task :clear_db => :environment do |t,args|
  ActiveRecord::Base.establish_connection
  ActiveRecord::Base.connection.tables.each do |table|
    next if table == 'schema_migrations'
    ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
  end
end

desc 'Delete all tables (but not the database)'
task :drop_schema => :environment do |t,args|
  ActiveRecord::Base.establish_connection
  ActiveRecord::Base.connection.execute("DROP SCHEMA public CASCADE")
  ActiveRecord::Base.connection.execute("CREATE SCHEMA public")
  ActiveRecord::Base.connection.execute("GRANT ALL ON SCHEMA public TO postgres")
  ActiveRecord::Base.connection.execute("GRANT ALL ON SCHEMA public TO public")
  ActiveRecord::Base.connection.execute("COMMENT ON SCHEMA public IS 'standard public schema'")
end

desc 'Recreate the database and seed'
task :redo_db => :environment do |t,args|
  # Executes the dependencies, but only once
  Rake::Task["db:drop_schema"].invoke
  Rake::Task["db:migrate"].invoke
  Rake::Task["db:migrate:status"].invoke 
  Rake::Task["db:structure:dump"].invoke
  Rake::Task["db:seed"].invoke
end

end

0

远程方案。但是,如果您尝试在Rails应用中运行测试,则会得到类似

“” ActiveRecord :: StatementInvalid:PG :: ObjectInUse:错误:其他用户正在访问数据库“ myapp_test”细节:使用该数据库还有另外1个会话。“

在运行测试之前,请确保关闭pgAdmin或任何其他postgres GUI工具。


0

案例:
无法执行查询:

DROP TABLE dbo.t_tabelname

解决方案:
一。显示查询状态活动,如下所示:

SELECT * FROM pg_stat_activity  ;

b。查找“查询”列包含的行:

'DROP TABLE dbo.t_tabelname'

C。在同一行中,获取“ PID”列的值

example : 16409

d。执行以下脚本:

SELECT 
    pg_terminate_backend(25263) 
FROM 
    pg_stat_activity 
WHERE 
    -- don't kill my own connection!
    25263 <> pg_backend_pid()
    -- don't kill the connections to other databases
    AND datname = 'database_name'
    ;


0

打开PGadmin,看看是否有任何查询页面打开,关闭所有查询页面并断开PostgresSQL服务器的连接,然后再次连接它并尝试使用Delete / drop选项。


0

在PG管理员中,您可以断开服务器连接(右键单击服务器),并且所有会话将在重新启动时断开连接


0

对我来说,它从事以下工作:

sudo gitlab-ctl stop
sudo gitlab-ctl start gitaly
sudo gitlab-rake gitlab:setup [type yes and let it finish]
sudo gitlab-ctl start

我正在使用:
gitlab_edition:“ gitlab-ce”
gitlab_version:'12 .4.0-ce.0.el7'


0

首先,找到Postgres运行哪个端口

  1. ps -ef | grep postgres

    它会返回端口号

  2. 杀-9 port_number

最后再次启动Postgres

brew services start postgresql 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.