Là một truy vấn chạy dài Postgres bị hủy bỏ nếu kết nối bị mất / bị hỏng?


20

Nếu tôi mở một kết nối tới Postgres và đưa ra một truy vấn chạy dài, sau đó ngắt kết nối (ví dụ: giết tiến trình máy khách đã mở kết nối), liệu truy vấn chạy dài có tiếp tục chạy hay nó sẽ tự động bị hủy bỏ? Đây có phải là cấu hình?

(Tôi đang sử dụng Postgresql 9.2.9)

Câu trả lời:


32

"Nó phụ thuộc".

Nếu máy khách biến mất do mất kết nối mạng, truy vấn thường sẽ chạy cho đến khi nó lấy đủ số hàng để điền vào bộ đệm gửi mạng của nó, sau đó dừng và bị kẹt cho đến khi kết nối TCP bị hủy, tại thời điểm đó nó sẽ hủy bỏ. Nếu nó hoàn thành trước khi nó lấp đầy bộ đệm gửi TCP, nó sẽ hoàn thành thành công, vì vậy nếu nó tự động truy vấn sẽ cam kết.

Nếu máy khách bị giết theo cách mà hệ điều hành của máy khách có thể báo cáo với máy chủ thông qua RST TCP (như segfault / crash của máy khách, SIGTERM, SIGKILL, v.v.), máy chủ PostgreQuery sẽ đặt cờ ngắt. Lần tới khi truy vấn kiểm tra các ngắt vì nó thực thi nó sẽ thấy cờ và hủy bỏ. Đôi khi, một truy vấn có thể thực hiện công việc nặng về CPU trong mã không kiểm tra các ngắt - một số tiện ích mở rộng và một vài vị trí trong lõi PostgreQuery - trong trường hợp đó có thể không nhận thấy ngắt trong một thời gian dài và tiếp tục chạy. Mặc dù vậy, mọi người sẽ luôn thấy sự gián đoạn và hủy bỏ trước khi hoàn thành và cam kết nếu đó là tự động.

Nếu máy khách bị giết bởi thứ gì đó giống như khởi động lại hệ điều hành đột ngột, để máy chủ máy khách đột nhiên không biết gì về kết nối TCP nhưng vẫn có thể phản hồi trên mạng, truy vấn có thể sẽ bị hủy bỏ khi lần đầu tiên kiểm tra để viết một hàng, như Jeff cho biết, vì máy chủ của máy khách sẽ gửi RST TCP để phản hồi gói đầu tiên được gửi bởi máy chủ sau khi khởi động lại. PostgreSQL kiểm tra các ngắt ở mỗi hàng mà nó gửi.

Hành vi này không thể cấu hình. Theo như PostgreSQL có liên quan nếu máy khách biến mất, công việc của nó là chấm dứt mọi truy vấn mà máy khách đang chạy. Để thay đổi rằng bạn cần một số loại mã thông báo hoàn thành truy vấn mà bạn có thể nhận được khi bắt đầu truy vấn, sau đó sử dụng để hỏi máy chủ về truy vấn thông qua kết nối khác sau đó. Về cơ bản, bạn phải thực hiện các truy vấn không đồng bộ / nền. Có thể là một tính năng tốt, nhưng hiện không được hỗ trợ.

Nếu truy vấn là tự động hoặc nếu truy vấn của bạn là COMMIT chuyến bay đang trong thời gian bạn giết khách hàng / mất kết nối, thì giao dịch có thể ở trạng thái không xác định khi khách hàng không biết liệu có hay không không phải nó cam kết. Không có cách nào thực sự để tìm hiểu, ngoài việc tìm kiếm những ảnh hưởng của giao dịch trên dữ liệu.

Trong trường hợp không thể chấp nhận, bạn có thể sử dụng cam kết hai pha và trình quản lý giao dịch phía khách hàng.


1
Wow, chỉ là những gì tôi đang tìm kiếm, một câu trả lời chi tiết tuyệt vời! Cảm ơn @Craig_Ringer!
Rob Bednark


2

Nó sẽ tiếp tục chạy cho đến khi nó cố gắng trả các hàng về kết nối và phát hiện sự cố. Vì vậy, đối với một truy vấn thực hiện tất cả công việc trước khi trả về bất kỳ hàng nào, về cơ bản nó sẽ chạy để hoàn thành.


Cảm ơn @jjanes. Bạn có thể chỉ ra bất kỳ tài liệu hoặc mã nguồn chỉ ra điều này?
Rob Bednark
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.