2011-02-24 124 views
232

如何杀死我所有的postgresql连接?杀死postgresql会话/连接

我想一个rake db:drop但我得到:

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

我试图关闭我从ps -ef | grep postgres看到的过程,但这个不起作用或者:

kill: kill 2358 failed: operation not permitted 

回答

430

你可以使用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' 
    ; 

之前执行这个查询,你必须REVOKE的CONNECT权限,以避免新的连接:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username; 

If you're using Postgres 8.4-9.1 use procpid instead of 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' 
    ; 
+59

注意,在Postgres 9.2,procpid被重命名为pid。 – Devin 2012-12-04 22:39:44

+7

谢谢!把它变成一个耙子任务:https://gist.github.com/mfilej/5943114 – mfilej 2013-07-07 11:11:09

+0

如果他是一个超级用户,不管他有没有'sudo'-ed杀了? – ndn 2016-03-11 14:45:47

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 

从发现中发现herehere

Here's a modified version适用于PostgreSQL 9.1和9.2。

4

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

编辑:

此外,as an absolute last resort你可以备份你的数据,那么运行这个命令:

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

...这将杀死Postgres的用户正在访问的一切。避免在生产机器上这样做,但不应该对开发环境有问题。确保每个postgres进程在尝试重新启动PostgreSQL之前已经真正终止是至关重要的。

编辑2:

由于this unix.SE post我从kill -9变更为kill -15

+1

在我有限的Navicat Lite经验中,简单地关闭数据库或服务器连接并不总是足够的。 Navicat Lite似乎保持偶尔的连接,直到应用程序终止。 – ken 2013-06-05 13:32:47

11

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

+2

或'brew服务重启postgresql' – PJSCopeland 2017-10-25 01:03:45

+0

@PJSCopeland感谢您的最简单的解决方案!我认为您的意见应该是一个真正的答案,因此:https://stackoverflow.com/a/48226667/1097104 – 2018-01-12 12:52:53

+0

感谢你,@JuusoOhtonen。告诉你什么,如果你想从它的声誉,你至少可以链接回我的评论? – PJSCopeland 2018-01-14 20:54:02

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+

+0

对于Postgres 9.1及更高版本,您需要使用'pg_stat_activity.procpid'而不是'pg_stat_activity.pid'。请参阅http://stackoverflow.com/a/5408501/444774 – talyric 2013-05-09 23:44:58

+1

这是一个很好的答案!它比Rails默认更好也更安全。谢谢! – piersadrian 2013-07-12 23:12:19

146

也许只是重新启动postgres =>sudo service postgresql restart

+7

惊人的答案!安全和简单 – Starkers 2014-08-18 00:05:33

+0

@标记我经历了上面的大部分答案,直到它在我身上恍然大悟:) – 2014-08-18 13:35:54

+14

@Starkers是的,特别是在高负荷下安全生产;) – Erathiel 2016-04-05 06:22:29

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 
1

只是想指出,如果一些其他的后台进程是使用数据库,在我的情况下,它被推迟就业哈里斯的回答可能无法正常工作,我所做的:

script/delayed_job stop 

才把我能够删除/重置数据库。

0

远程场景。但是,如果你想运行在一个Rails应用程序测试,你喜欢的东西

“的ActiveRecord :: StatementInvalid:PG :: ObjectInUse:错误:数据库‘myapp_test’正被其他用户访问 详细信息:有是另外一个使用数据库的会话。“

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

-1

案例:
无法执行查询:

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' 
    ; 
2

退出postgres并重新启动它。简单,但每次都适用于我,其他cli命令有时不会。

+0

简单而有效!为了进一步澄清pgAdmin 4并重新启动 – 2017-04-08 02:12:57

2

我已经解决这样说:

在我Windows8的64位,只是restart荷兰国际集团服务:PostgreSQL的-x64-9。5

+1

这只是重新启动,这通常不适用于生产环境,因此关闭拥抱进程是一种更理想的选择。 – BrianC 2017-04-01 15:54:59

12

随着对运行过程中的所有相关信息:

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