Tuer une session / connexion postgresql


371

Comment puis-je tuer toutes mes connexions postgresql?

J'essaye un rake db:dropmais j'obtiens:

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

J'ai essayé d'arrêter les processus que je vois d'un ps -ef | grep postgresmais cela ne fonctionne pas non plus:

kill: kill 2358 failed: operation not permitted

Lorsque toutes les autres tentatives ont échoué, la gemme pgreset a en quelque sorte fixé les rails / pg en pensant qu'une connexion existait, ce qui n'a pas été le cas.
JosephK

Réponses:


673

Vous pouvez utiliser pg_terminate_backend () pour tuer une connexion. Vous devez être superutilisateur pour utiliser cette fonction. Cela fonctionne sur tous les systèmes d'exploitation de la même manière.

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

Avant d'exécuter cette requête, vous devez RÉVOQUER les privilèges CONNECT pour éviter de nouvelles connexions:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Si vous utilisez Postgres 8.4-9.1, utilisez procpid au lieu de 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
Notez que dans Postgres 9.2, procpid est renommé pid.
Devin

S'il était un super-utilisateur, n'aurait-il pas pu sudotuer de toute façon?
ndnenkov

3
@ndn Un superutilisateur de base de données n'est pas la même chose qu'un superutilisateur de niveau OS. Il n'y sudoen a pas dans PG.
jpmc26

C'est la seule réponse qui fonctionne pour de nombreuses questions SO, car elle a l' REVOKEétape. Vous avez sauvé quelqu'un, encore une fois je suppose!
AymDev

Cela fonctionne grâce ....
Ajay Kumar

205

Peut-être juste redémarrer postgres=>sudo service postgresql restart


@Starkers J'ai parcouru la plupart des réponses ci-dessus, jusqu'à ce qu'il me vienne à l'esprit :)
Haris Krajina

32
@Starkers Oui, particulièrement sûr en production sous forte charge;)
Erathiel

10
brew services restart postgresqlsi vous avez
préparé

28

Avec toutes les informations sur le processus en cours:

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


13

OSX, Postgres 9.2 (installé avec homebrew)

$ 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


Si votre datadir est ailleurs, vous pouvez savoir où il se trouve en examinant la sortie de ps aux | grep postgres


4
Oubrew services restart postgresql
PJSCopeland

@PJSCopeland Merci pour la solution la plus simple! Je pense que votre commentaire mérite d'être une vraie réponse, donc: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen

Merci pour cela, @JuusoOhtonen. Dites-vous que si, si vous en voulez la réputation, vous pouvez au moins renvoyer à mon commentaire?
PJSCopeland

@PJSCopeland Done.
Juuso Ohtonen

A eu des problèmes avec d'autres réponses et d'autres solutions de publication SO similaires. L'exécution de votre pg_ctl restart -D /usr/local/var/postgresfait l'affaire! (Je n'ai même pas exécuté la première ou la troisième commande).
Iggy

8

Cela semble fonctionner pour 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

Sorti des esprits trouvés ici et ici .

Voici une version modifiée qui fonctionne pour PostgreSQL 9.1 et 9.2.


6

J'utilise la tâche de râteau suivante pour remplacer la drop_databaseméthode Rails .

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

Edit: c'est pour Postgresql 9.2+


Vous devez utiliser à la pg_stat_activity.procpidplace de pg_stat_activity.pidPostgres 9.1 et ci-dessous. Voir stackoverflow.com/a/5408501/444774
talyric

1
C'est une excellente réponse! C'est mieux et plus sûr que le Rails par défaut. Merci!
piersadrian

5

Un moyen plus simple et plus mis à jour est:

  1. Utilisez ps -ef | grep postgrespour trouver la connexion #
  2. sudo kill -9 "#" de la connexion

Remarque: Il peut y avoir un PID identique. Tuer un tue tout.


3

J'ai eu ce problème et le problème était que Navicat était connecté à ma base de données Postgres locale. Une fois que j'ai déconnecté Navicat, le problème a disparu.

ÉDITER:

De plus, en dernier recours, vous pouvez sauvegarder vos données, puis exécuter cette commande:

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

... qui tuera tout ce à quoi l'utilisateur postgres accède. Évitez de le faire sur une machine de production, mais vous ne devriez pas avoir de problème avec un environnement de développement. Il est essentiel que vous vous assuriez que chaque postgres processus est vraiment terminé avant de tenter de redémarrer PostgreSQL après cela.

EDIT 2:

En raison de ce message unix.SE, je suis passé de kill -9à kill -15.


1
Dans mon expérience limitée avec Navicat Lite, il ne suffit pas toujours de fermer la connexion à la base de données ou au serveur. Navicat Lite semble garder la connexion occasionnelle ouverte jusqu'à la fin de l'application.
ken

3

J'AI RÉSOLU DE CETTE FAÇON:

Dans mon Windows8 64 bits, juste restartle service: postgresql-x64-9.5


5
C'est juste un redémarrage qui n'est généralement pas souhaitable pour les environnements de production, tuer le processus de câlin est une option beaucoup plus souhaitable.
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

Je voulais juste souligner que la réponse de Haris pourrait ne pas fonctionner si un autre processus d'arrière-plan utilise la base de données, dans mon cas, il s'agissait de travaux retardés, j'ai fait:

script/delayed_job stop

Et seulement alors, j'ai pu supprimer / réinitialiser la base de données.


1

Quittez postgres et redémarrez-le. Simple, mais fonctionne à chaque fois pour moi, contrairement aux autres commandes cli.


Simple et fonctionne! Pour clarifier davantage tout à fait pgAdmin 4 et redémarrer
Ka Tech

0

Il n'est pas nécessaire de l'abandonner. Supprimez et recréez simplement le schéma public. Dans la plupart des cas, cela a exactement le même effet.

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

Scénario distant. Mais si vous essayez d'exécuter des tests dans une application rails, et que vous obtenez quelque chose comme

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERREUR: la base de données" myapp_test "est accédée par d'autres utilisateurs DÉTAIL: Il y a 1 autre session utilisant la base de données."

Assurez-vous de fermer pgAdmin ou tout autre outil GUI postgres avant d'exécuter des tests.


0

Cas:
échec d'exécution de la requête:

DROP TABLE dbo.t_tabelname

Solution:
a. Afficher l'activité d'état de la requête comme suit:

SELECT * FROM pg_stat_activity  ;

b. Recherchez la ligne contenant la colonne "Requête":

'DROP TABLE dbo.t_tabelname'

c. Dans la même ligne, obtenez la valeur de la colonne 'PID'

example : 16409

ré. Exécutez ces scripts:

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

Je suis sur un Mac et j'utilise PostgreSQL via Postgres.app. J'ai résolu ce problème en quittant et en redémarrant l'application.


0

Ouvrez PGadmin pour voir s'il y a une page de requête ouverte, fermez toutes les pages de requête et déconnectez le serveur PostgresSQL et connectez-le à nouveau et essayez l'option de suppression / suppression. Cela m'a aidé.


0

Dans PG admin, vous pouvez déconnecter votre serveur (clic droit sur le serveur) et toutes les sessions seront déconnectées au redémarrage


0

Pour moi, a travaillé ce qui suit:

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

J'utilise:
gitlab_edition: "gitlab-ce"
gitlab_version: '12 .4.0-ce.0.el7 '


0

Tout d'abord, trouvez Postgres qui porte son fonctionnement

  1. ps -ef | grep postgres

    son renverra le numéro de port

  2. tuer -9 port_number

Enfin, recommencez Postgres

brew services start postgresql 
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.