Rails + Postgres drop error:其他用户正在访问数据库

fju*_*uan 83 postgresql ruby-on-rails

我有一个在Postgres上运行的rails应用程序.

我有两台服务器:一台用于测试,另一台用于生产.

我经常需要在测试服务器上克隆生产数据库.

我通过弗拉德跑的命令是:

rake RAILS_ENV='test_server' db:drop db:create
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我收到以下错误:

ActiveRecord::StatementInvalid: PGError: ERROR: database <database_name> is being accessed by other users DROP DATABASE IF EXISTS <database_name>
Run Code Online (Sandbox Code Playgroud)

如果有人最近通过网络访问了该应用程序(postgres保持"会话"打开),就会发生这种情况

有什么方法可以终止postgres DB上的会话吗?

谢谢.

编辑

我可以使用phppgadmin的界面删除数据库,但不能使用rake任务删除数据库.

如何使用rake任务复制phppgadmin的drop?

enc*_*ded 76

如果您为应用程序终止正在运行的postgresql连接,则可以运行db:drop就好了.那么如何杀死这些联系呢?我使用以下rake任务:

# lib/tasks/kill_postgres_connections.rake
task :kill_postgres_connections => :environment do
  db_name = "#{File.basename(Rails.root)}_#{Rails.env}"
  sh = <<EOF
ps xa \
  | grep postgres: \
  | grep #{db_name} \
  | grep -v grep \
  | awk '{print $1}' \
  | xargs kill
EOF
  puts `#{sh}`
end

task "db:drop" => :kill_postgres_connections
Run Code Online (Sandbox Code Playgroud)

在下一次尝试加载页面时,从轨道下方取消连接有时会导致它被禁止,但重新加载它会重新建立连接.

  • `task"db:drop"=>:kill_postgres_connections`我认为应该删除这一行,从我的角度来看,扩展系统任务的行为是危险的. (6认同)
  • 我不得不向xargs添加sudo并更改数据库名称,但它可以工作.TY (2认同)

Mr.*_*ene 33

更简单,更新的方式是:1.ps -ef | grep postgres用于查找连接#2.sudo kill -9 "# of the connection

注意:可能存在相同的PID.杀一个杀死所有人.

  • @BradGreens 第二列(我使用的是 Mac 终端) (3认同)

Jam*_*ren 16

这是一种快速杀死postgres数据库的所有连接的方法.

sudo kill -9 `ps -u postgres -o pid` 
Run Code Online (Sandbox Code Playgroud)

警告:这将终止postgres用户已打开的任何正在运行的进程,因此请确保首先执行此操作.

  • 在我的系统中,我使用``sudo kill -9` ps -u postgres -o pid =```代替,因此`ps`不会打印*PID*头,所以字符串参数不会传递给` kill`,所以不会引发错误.在任何情况下都很棒. (8认同)
  • 如果您使用的是 Ubuntu,请使用它再次启动 postgresql:`sudo service postgresql start` (3认同)

use*_*745 10

步骤1

获取所有 postgres 连接的列表ps -ef | grep postgres

该列表将如下所示:

  502   560   553   0 Thu08am ??         0:00.69 postgres: checkpointer process             
  502   565   553   0 Thu08am ??         0:00.06 postgres: bgworker: logical replication launcher
  502 45605   553   0  2:23am ??         0:00.01 postgres: st myapp_development [local] idle 
Run Code Online (Sandbox Code Playgroud)

第2步

停止您想要的任何连接sudo kill -9 <pid>,其中pid是第二列中的值。就我而言,我想用 pid 停止最后一行45605,所以我使用:

sudo kill -9 45605
Run Code Online (Sandbox Code Playgroud)


Mat*_*oti 9

当我们使用上面的"kill processes"方法时,db:drop失败了(如果:kill_postgres_connections是先决条件).我相信这是因为rake命令正在使用的连接被杀死了.相反,我们使用sql命令删除连接.这作为db:drop的先决条件,避免了通过相当复杂的命令杀死进程的风险,它应该适用于任何操作系统(gentoo需要不同的语法kill).

cmd = %(psql -c "SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE procpid <> pg_backend_pid();" -d '#{db_name}')
Run Code Online (Sandbox Code Playgroud)

这是一个rake任务,它从database.yml读取数据库名称并运行改进的(IMHO)命令.它还添加了db:kill_postgres_connections作为db:drop的先决条件.它包含一个警告,在您升级rails后会大喊,表示可能不再需要此修补程序.

请参阅:https://gist.github.com/4455341,包含参考资料


Chr*_*son 7

我使用以下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
Run Code Online (Sandbox Code Playgroud)


Fra*_*ens 5

让应用程序在完成后关闭连接.PostgreSQL不保持连接打开,它是保持连接的应用程序.


小智 5

请检查您的rails控制台或服务器是否在另一个选项卡中运行

停止rails服务器和控制台.

然后运行

 rake db:drop
Run Code Online (Sandbox Code Playgroud)