Giết một phiên / kết nối postgresql


369

Làm thế nào tôi có thể giết tất cả các kết nối postgresql của tôi?

Tôi đang thử rake db:dropnhưng tôi nhận được:

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

Tôi đã thử tắt các quy trình tôi thấy từ một ps -ef | grep postgresnhưng điều này cũng không hoạt động:

kill: kill 2358 failed: operation not permitted

Khi tất cả các nỗ lực khác không thành công, đá quý pgreset bằng cách nào đó đã cố định đường ray / pg nghĩ rằng có một kết nối tồn tại, điều đó không xảy ra.
JosephK

Câu trả lời:


671

Bạn có thể sử dụng pg_terminate_backend () để hủy kết nối. Bạn phải là siêu người dùng để sử dụng chức năng này. Điều này hoạt động trên tất cả các hệ điều hành như nhau.

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

Trước khi thực hiện truy vấn này, bạn phải REVOKE các đặc quyền CONNECT để tránh các kết nối mới:

REVOKE CONNECT ON DATABASE dbname FROM PUBLIC, username;

Nếu bạn đang sử dụng Postgres 8.4-9.1, hãy sử dụng Procpid thay vì 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
Lưu ý rằng trong Postgres 9.2, Procpid được đổi tên thành pid.
Devin

Nếu anh ta là một siêu nhân, sudodù sao anh ta cũng không thể giết được?
ndnenkov 11/03/2016

3
@ndn Một siêu người dùng cơ sở dữ liệu không giống như một siêu người dùng cấp hệ điều hành. Không có sudotrong PG.
jpmc26

Đây là câu trả lời duy nhất cho nhiều câu hỏi SO vì nó có REVOKEbước. Bạn đã cứu ai đó, một lần nữa tôi đoán!
AymDev

Điều này hoạt động cảm ơn ....
Ajay Kumar

205

Có lẽ chỉ cần khởi động lại postgres=>sudo service postgresql restart


@Starkers Tôi đã trải qua hầu hết các câu trả lời ở trên, cho đến khi nó hiểu ra tôi :)
Haris Krajina

32
@Starkers Có, đặc biệt an toàn trong sản xuất dưới tải trọng cao;)
Erathiel

10
brew services restart postgresqlnếu bạn có bia
Sam Kah Chiin

28

Với tất cả các thông tin về quá trình chạy:

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


13

OSX, Postgres 9.2 (được cài đặt với 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


Nếu datadir của bạn ở nơi khác, bạn có thể tìm ra nó ở đâu bằng cách kiểm tra đầu ra của ps aux | grep postgres


4
Hoặcbrew services restart postgresql
PJSCopeland

@PJSCopeland Cảm ơn giải pháp đơn giản nhất! Tôi nghĩ rằng nhận xét của bạn xứng đáng là một câu trả lời thực sự, do đó: stackoverflow.com/a/48226667/1097104
Juuso Ohtonen

Cảm ơn vì điều đó, @JuusoOhtonen. Cho bạn biết những gì mặc dù, nếu bạn muốn danh tiếng từ nó, ít nhất bạn có thể liên kết lại với nhận xét của tôi?
PJSCopeland

@PJSCopeland Xong.
Juuso Ohtonen

Có vấn đề với câu trả lời khác và các giải pháp bài SO tương tự khác. Chạy của bạn pg_ctl restart -D /usr/local/var/postgresđã lừa (Tôi thậm chí không chạy lệnh đầu tiên hoặc thứ ba).
Iggy

8

Điều này dường như đang hoạt động cho 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

Nâng lên từ các ý chính được tìm thấy ở đâyở đây .

Đây là phiên bản sửa đổi hoạt động cho cả PostgreQuery 9.1 và 9.2.


6

Tôi sử dụng tác vụ cào sau để ghi đè drop_databasephương thức 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

Chỉnh sửa: Đây là cho Postgresql 9.2+


Bạn cần sử dụng pg_stat_activity.procpidthay vì pg_stat_activity.pidcho Postgres 9.1 trở xuống. Xem stackoverflow.com/a/5408501/444774
talyric

1
Đây là một câu trả lời tuyệt vời! Nó tốt hơn và an toàn hơn mặc định của Rails. Cảm ơn!
piersadrian

5

Cách dễ dàng và cập nhật hơn là:

  1. Sử dụng ps -ef | grep postgresđể tìm kết nối #
  2. sudo kill -9 "#" của kết nối

Lưu ý: Có thể có PID giống hệt nhau. Giết một người giết chết tất cả.


3

Tôi đã có vấn đề này và vấn đề là Navicat đã được kết nối với db Postgres địa phương của tôi. Khi tôi ngắt kết nối Navicat, vấn đề biến mất.

BIÊN TẬP:

Ngoài ra, như một phương sách cuối cùng tuyệt đối, bạn có thể sao lưu dữ liệu của mình sau đó chạy lệnh này:

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

... Nó sẽ giết mọi thứ mà người dùng postgres đang truy cập. Tránh làm điều này trên một máy sản xuất nhưng bạn không nên có vấn đề với môi trường phát triển. Điều quan trọng là bạn đảm bảo mọi postgres quy trình đã thực sự chấm dứt trước khi thử khởi động lại PostgreSQL sau việc này.

EDIT 2:

Do bài unix.SE này tôi đã thay đổi từ kill -9tới kill -15.


1
Theo kinh nghiệm hạn chế của tôi với Navicat Lite, chỉ cần đóng cơ sở dữ liệu hoặc kết nối máy chủ không phải lúc nào cũng đủ. Navicat Lite dường như giữ kết nối không thường xuyên mở cho đến khi ứng dụng bị chấm dứt.
ken

3

TÔI ĐÃ GIẢI QUYẾT CÁCH NÀY:

Trong Windows8 64 bit của tôi , chỉ cần restartsử dụng dịch vụ: postgresql-x64-9.5


5
Đó chỉ là thực hiện khởi động lại thường không mong muốn đối với môi trường sản xuất, giết quá trình ôm là một lựa chọn đáng mong đợi hơn nhiều.
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

Chỉ muốn chỉ ra rằng Câu trả lời của Haris có thể không hoạt động nếu một số quy trình nền khác đang sử dụng cơ sở dữ liệu, trong trường hợp của tôi, đó là công việc bị trì hoãn, tôi đã làm:

script/delayed_job stop

Và chỉ sau đó tôi mới có thể thả / thiết lập lại cơ sở dữ liệu.


1

Thoát khỏi postgres và khởi động lại nó. Đơn giản, nhưng hoạt động mọi lúc đối với tôi, nơi các lệnh cli khác đôi khi không.


Đơn giản và hiệu quả! Để làm rõ hơn nữa pgAdmin 4 và khởi động lại
Ka Tech

0

Không cần phải bỏ nó. Chỉ cần xóa và tạo lại lược đồ công cộng. Trong hầu hết các trường hợp, điều này có tác dụng chính xác như nhau.

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

Kịch bản từ xa. Nhưng nếu bạn đang cố chạy thử nghiệm trong ứng dụng rails và bạn sẽ nhận được một cái gì đó như

"ActiveRecord :: StatementInvalid: PG :: ObjectInUse: ERROR: cơ sở dữ liệu" myapp_test "đang được người dùng khác truy cập CHI TIẾT: Có 1 phiên khác sử dụng cơ sở dữ liệu."

Đảm bảo bạn đóng pgAdmin hoặc bất kỳ công cụ GUI nào khác trước khi chạy thử nghiệm.


0

Trường hợp:
Không thực hiện truy vấn:

DROP TABLE dbo.t_tabelname

Lời giải:
a. Hiển thị trạng thái truy vấn Hoạt động như sau:

SELECT * FROM pg_stat_activity  ;

b. Tìm hàng trong đó cột 'Truy vấn' có chứa:

'DROP TABLE dbo.t_tabelname'

c. Trong cùng một hàng, nhận giá trị của Cột 'PID'

example : 16409

d. Thực thi các tập lệnh này:

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

Tôi đang dùng mac và tôi sử dụng postgres qua Postgres.app. Tôi đã giải quyết vấn đề này chỉ cần bỏ và bắt đầu lại ứng dụng.


0

Mở PGadmin xem có trang truy vấn nào mở không, đóng tất cả trang truy vấn và ngắt kết nối máy chủ PostgresQuery và Kết nối lại và thử tùy chọn xóa / thả. Điều này đã giúp tôi.


0

Trong quản trị viên PG, bạn có thể ngắt kết nối máy chủ của mình (nhấp chuột phải vào máy chủ) và tất cả các phiên sẽ bị ngắt kết nối khi khởi động lại


0

Đối với tôi làm việc như sau:

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

Tôi đang sử dụng:
gitlab_edition: "gitlab-ce"
gitlab_version: '12 .4.0-ce.0.el7 '


0

Đầu tiên, tìm Postgres mà cổng đang chạy

  1. ps -ef | grep postgres

    nó sẽ trả về số cổng

  2. giết -9 port_number

Cuối cùng lại bắt đầu Postgres

brew services start postgresql 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.