Heroku Postgres - chấm dứt truy vấn treo (không hoạt động trong giao dịch)


99

Tôi đang sử dụng Heroku với tùy chọn Crane Postgres và tôi đang chạy một truy vấn trên cơ sở dữ liệu từ máy cục bộ của mình khi máy cục bộ của tôi gặp sự cố. Nếu tôi chạy

select * from pg_stat_activity

một trong những mục có

<IDLE> in transaction

trong cột current_query_text.

Do đó, tôi không thể bỏ bảng đang được ghi bởi truy vấn đã bị chấm dứt. Tôi đã thử sử dụng pg_cancel_backend (N) và nó trả về True nhưng dường như không có gì xảy ra.

Làm cách nào để chấm dứt quá trình này để tôi có thể rời khỏi bảng?


1
Có lẽ câu hỏi nên được diễn đạt lại thành "làm cách nào để chấm dứt truy vấn của chính mình khi không có quyền truy cập root vào máy chủ postgres cũng như quyền truy cập siêu người dùng vào cơ sở dữ liệu". Nó thực sự là một câu hỏi rất hay ... và tôi không biết câu trả lời.
tobixen

Câu trả lời:


138

Đây là câu trả lời chung của Postgres, và không dành riêng cho heroku


(Câu trả lời đơn giản-ngu ngốc cho câu hỏi này có thể là ... chỉ cần khởi động lại postgresql. Giả sử đó không phải là mong muốn hoặc không phải là một tùy chọn ...)

Tìm PID bằng cách chạy sql này:

SELECT pid , query, * from pg_stat_activity
  WHERE state != 'idle' ORDER BY xact_start;

(Truy vấn có thể cần sửa chữa tùy thuộc vào phiên bản của postgres - cuối cùng, chỉ cần chọn * từ pg_stat_activity). Bạn sẽ tìm thấy pid trong cột đầu tiên (bên trái) và hàng đầu tiên (trên cùng) có thể là truy vấn bạn muốn kết thúc. Tôi giả sử pid là 1234 bên dưới.

Bạn có thể hủy truy vấn thông qua SQL (tức là không có quyền truy cập shell) miễn là truy vấn của bạn hoặc bạn có quyền truy cập cấp cao:

select pg_cancel_backend(1234);

Đó là một yêu cầu "thân thiện" để hủy truy vấn 1234 và may mắn là nó sẽ biến mất sau một thời gian. Cuối cùng, điều này hiệu quả hơn:

select pg_terminate_backend(1234);

Nếu bạn có quyền truy cập shell và quyền root hoặc postgres, bạn cũng có thể làm điều đó từ shell. Để "hủy" người ta có thể làm:

kill -INT 1234

và để "chấm dứt", chỉ cần:

kill 1234

ĐỪNG:

kill -9 1234

... điều đó thường dẫn đến toàn bộ máy chủ postgres chìm trong biển lửa, sau đó bạn cũng có thể khởi động lại postgres. Postgres khá mạnh mẽ, vì vậy dữ liệu sẽ không bị hỏng, nhưng tôi khuyên bạn không nên sử dụng "kill -9" trong mọi trường hợp :-)


"Giao dịch không hoạt động" kéo dài thường có nghĩa là giao dịch không được kết thúc bằng "cam kết" hoặc "khôi phục", có nghĩa là ứng dụng có lỗi hoặc không được thiết kế phù hợp để hoạt động với cơ sở dữ liệu giao dịch. Cần tránh tình trạng "nhàn rỗi trong giao dịch" kéo dài, vì nó cũng có thể gây ra các vấn đề lớn về hiệu suất.


Tôi đã thử pg_cancel_backend nhưng không có kết quả. Tôi không có quyền truy cập shell và tôi không phải là siêu người dùng nên tôi không thể gửi SIGKILL bằng pg_termina_backend
alan

Bạn đang sử dụng phiên bản postgres nào? (gợi ý select version():). Bạn có nhận được thông báo lỗi nào khi sử dụng pg_cancel_backendkhông?
tobixen

Tôi đã cố gắng sử dụng pg_cancel_backend, do đó, nhận được thông báo lỗi "phải là superuser để báo hiệu các quy trình máy chủ khác" ... có nghĩa là bạn sẽ cần quyền truy cập root trên máy chủ hoặc quyền truy cập db thông qua một số postgres super user (tức là người dùng postgres ) để loại bỏ truy vấn của riêng bạn. Mà dường như để hút một chút :-(
tobixen

1
hóa ra các quy trình đã bị hủy bởi pg_cancel_backend nhưng các truy vấn vẫn hiển thị trong pg_stat_activity trong một thời gian
alan

Có lẽ nó dành riêng cho Heroku. Theo như tôi thấy, dưới những postgres thông thường, thực sự cần phải là superuser để giết một quy trình bị mắc kẹt (tôi đang thử nghiệm với "select pg_sleep (3600);" trên trang 8.4 và tôi nhận được "LỖI: phải là superuser để báo hiệu các quy trình máy chủ khác "). Mặc dù vậy, một lần nữa "nhàn rỗi trong giao dịch" không hoàn toàn giống nhau.
tobixen

36

Thử cái này:

select pg_terminate_backend(pid int)

Thêm về điều này bạn có thể tìm thấy ở đây . Đây nên là giải pháp 'sạch' của vấn đề này hơn là quá trình tiêu diệt bằng hệ thống.


Vui lòng thêm cách nhận pid vào câu trả lời của bạn
Mountainclimber

19

Bạn có thể cài đặt heroku-pg-extrastiện ích bổ sung và chạy lệnh sau để lấy PID:

heroku pg:locks --app <your-app>

Sau đó, chỉ cần làm:

heroku pg:kill <pid> --app <your-app> 

LƯU Ý : --forcetùy chọn có thể được sử dụng để phát hành pg_termina_backend làm mất toàn bộ kết nối cho truy vấn đó.

Nếu heroku pg:lockskhông liệt kê bất cứ điều gì, hãy thử heroku pg:ps.

Để biết thêm thông tin, hãy xem:
https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall


Cảm ơn bạn. Tôi vẫn không thể chấm dứt giao dịch / PID mặc dù ... máy tính của tôi đã bị đóng băng phần cứng trong quá trình nhập và tôi không thể chấm dứt PID. :(
dimitarvp

-3

Chúng ta có thể sử dụng những điều sau để đạt được điều đó trong một truy vấn:

SELECT pg_cancel_backend(pid), pg_terminate_backend(pid) FROM pg_stat_activity WHERE state != 'idle';

điều đó sẽ giết tất cả các truy vấn đang chạy, sau đó một truy vấn cũng có thể khởi động lại postgres. đặt hàng theo xact_start và giới hạn 1, và tôi có thể đồng ý ... nhưng sau đó, tôi muốn xem lại danh sách trước khi giết chết một cách mù quáng.
tobixen

cái này thì sao? SELECT pid, pg_cancel_backend(pid) FROM pg_stat_activity WHERE state != 'idle' AND (now() - query_start) > interval '5 minutes';
AFN
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.