关于数据库:杀死postgresql会话/连接

Kill a postgresql session/connection

我怎样才能杀死所有的PostgreSQL连接?

我正在尝试一个rake db:drop,但我得到:

1
2
ERROR:  DATABASE"database_name" IS being accessed BY other users
DETAIL:  There are 1 other SESSION(s) USING the DATABASE.

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

1
KILL: KILL 2358 failed: operation NOT permitted

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

1
2
3
4
5
6
7
8
9
10
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'
    ;

在执行此查询之前,必须撤消连接特权以避免新连接:

1
REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

If you're using Postgres 8.4-9.1 use procpid instead of pid

1
2
3
4
5
6
7
8
9
10
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'
    ;


也许只要重启postgres=>sudo service postgresql restart


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

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

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

1
2
3
$ 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的输出来确定它在哪里。


MacOS,如果PostgreSQL与BREW一起安装:

1
brew services restart postgresql

源:终止PostgreSQL会话/连接


这似乎适用于PostgreSQL 9.1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#{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。


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

lib/database.rake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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的+


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

编辑:

此外,作为绝对的最后手段,您可以备份数据,然后运行以下命令:

1
sudo KILL -15 `ps -u postgres -o pid`

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

编辑2:

由于这个unix.se帖子,我从kill -9改为kill -15


1
2
3
4
5
6
7
8
9
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

我是这样解决的:

在我的Windows8 64位中,只需restart使用服务:postgresql-x64-9.5


只是想指出,如果其他后台进程正在使用数据库,Haris的答案可能不起作用,在我的例子中,它是延迟的作业,我做到了:

1
script/delayed_job stop

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


退出Postgres并重新启动它。很简单,但每次都适用于我,而其他CLI命令有时不适用。


没有必要放弃它。只需删除并重新创建公共架构。在大多数情况下,这有着完全相同的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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

远程方案。但是如果你尝试在Rails应用程序中运行测试,你会得到

"ActiveRecord::StatementInvalid:pg::Objectinus:错误:其他用户正在访问数据库"myapp_test"。"详细信息:还有一个会话正在使用数据库。"

确保在运行测试之前关闭pgadmin或任何其他PostgresGUI工具。


打开pgadmin查看是否有任何查询页打开,关闭所有查询页并断开Postgressql服务器的连接,然后尝试删除/删除选项。这对我有帮助。


我在Mac上,我通过Postgres.app使用postgres。我解决了这个问题,只是退出并重新启动应用程序。


案例:执行查询失败:

1
DROP TABLE dbo.t_tabelname

解决方案:a.查询状态活动显示如下:

1
SELECT * FROM pg_stat_activity  ;

b.查找"查询"列包含以下内容的行:

1
'DROP TABLE dbo.t_tabelname'

c.在同一行中,获取"pid"列的值

1
example : 16409

d.执行这些脚本:

1
2
3
4
5
6
7
8
9
10
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'
    ;