2009-08-20 17 views
52

Tôi đã thiết lập Django để chạy một số tác vụ định kỳ trong các chủ đề của riêng mình và tôi nhận thấy rằng chúng luôn để lại các quy trình kết nối cơ sở dữ liệu chưa hoàn thành (pgsql "Idle In Transaction").Tác vụ Django được tạo luồng không tự động xử lý các giao dịch hoặc kết nối db?

Tôi đã xem qua nhật ký Postgres và thấy rằng các giao dịch không được hoàn thành (không có ROLLBACK). Tôi đã thử sử dụng các trang trí giao dịch khác nhau trên các chức năng của mình, không có may mắn.

Tôi đã chuyển sang quản lý giao dịch thủ công và đã thực hiện khôi phục thủ công, đã hoạt động, nhưng vẫn để lại các quy trình là "Không hoạt động".

Vì vậy, sau đó tôi gọi connection.close() và tất cả đều tốt.

Nhưng tôi đang tự hỏi, tại sao giao dịch và quản lý kết nối điển hình của Django không hoạt động đối với các tác vụ được tạo luồng này từ chuỗi chính của Django?

Trả lời

93

Sau nhiều tuần thử nghiệm và đọc mã nguồn Django, tôi đã tìm thấy câu trả lời cho câu hỏi của riêng tôi:

Giao dịch

hành vi autocommit mặc định của Django vẫn đúng với chức năng ren của tôi. Tuy nhiên, nó nêu trong tài liệu Django:

Ngay sau khi bạn thực hiện một hành động cần ghi vào cơ sở dữ liệu, Django sẽ tạo câu lệnh INSERT/UPDATE/DELETE và sau đó thực hiện COMMIT. Không có ROLLBACK tiềm ẩn nào.

Câu cuối cùng là rất theo nghĩa đen. Nó KHÔNG phát hành một lệnh ROLLBACK trừ khi một cái gì đó trong Django đã thiết lập cờ bẩn. Vì hàm của tôi chỉ thực hiện các câu lệnh SELECT nên nó không bao giờ thiết lập cờ bẩn và không kích hoạt một COMMIT.

Điều này đi ngược lại thực tế là PostgreSQL cho rằng giao dịch yêu cầu ROLLBACK vì Django đã ban hành lệnh SET cho múi giờ. Trong việc xem xét các bản ghi, tôi đã ném bản thân mình đi vì tôi tiếp tục nhìn thấy các câu lệnh ROLLBACK và giả định quản lý giao dịch của Django là nguồn. Hóa ra là không, và không sao.

Connections

Việc quản lý kết nối là nơi mà mọi thứ làm được khéo léo. Nó chỉ ra Django sử dụng signals.request_finished.connect(close_connection) để đóng kết nối cơ sở dữ liệu nó thường sử dụng. Vì không có gì bình thường xảy ra ở Django mà không liên quan đến yêu cầu, bạn sẽ thực hiện hành vi này.

Trong trường hợp của tôi, tuy nhiên, không có yêu cầu nào vì công việc đã được lên lịch. Không có yêu cầu có nghĩa là không có tín hiệu. Không có tín hiệu có nghĩa là kết nối cơ sở dữ liệu chưa bao giờ bị đóng.

Quay lại giao dịch, hóa ra chỉ cần thực hiện cuộc gọi đến connection.close() trong trường hợp không có bất kỳ thay đổi nào đối với các vấn đề quản lý giao dịch, câu lệnh ROLLBACK trong nhật ký PostgreSQL mà tôi đang tìm kiếm.

Giải pháp

Giải pháp là để cho phép người quản lý giao dịch Django bình thường để tiến hành như bình thường và chỉ đơn giản là đóng kết nối một trong ba cách:

  1. Viết trang trí đó đóng kết nối và bọc các chức năng cần thiết trong đó.
  2. Móc vào các tín hiệu yêu cầu hiện có để Django đóng kết nối.
  3. Đóng kết nối theo cách thủ công ở cuối hàm.

Bất kỳ người nào trong số ba người đó sẽ làm việc.

Điều này đã khiến tôi phát điên trong nhiều tuần. Tôi hy vọng điều này sẽ giúp người khác trong tương lai!

+1

Vui mừng bạn cuối cùng đã giải quyết vấn đề này. Nó không rõ ràng. Tôi tự hỏi nếu nó có thể có giá trị một vé để thêm một lưu ý trong các tài liệu ở đâu đó. –

+1

Vé này mô tả một vấn đề rất giống nhau: http://code.djangoproject.com/ticket/9964 – zooglash

+0

Wow. bất kỳ cơ hội nào mà bạn có thể chia sẻ mã? – Dejell

Các vấn đề liên quan