Các giao dịch trong PostgreSQL thông qua `psycopg2` trên mỗi con trỏ hoặc mỗi kết nối?


9

Tôi đang thực hiện một số công việc với PostgreQuery 9.3 bằng psycopg2API cơ sở dữ liệu.

Tôi có API DB được đặt ở mức cô lập tối thiểu (chế độ "tự động tự động") và đang quản lý các giao dịch của riêng tôi trực tiếp thông qua SQL. Thí dụ:

cur = self.conn.cursor()
cur.execute("BEGIN;")
cur.execute("SELECT dbId, downloadPath, fileName, tags FROM {tableName} WHERE dlState=%s".format(tableName=self.tableName), (2, ))
ret = cur.fetchall()
cur.execute("COMMIT;")

Về cơ bản, giao dịch được bắt đầu bởi cur.execute("BEGIN;")giới hạn chỉ con trỏ đó hay là cho toàn bộ kết nối ( self.conn.cursor())?

Một số điều phức tạp hơn tôi đang làm liên quan đến nhiều hoạt động cơ sở dữ liệu riêng biệt, mà tôi phân tích một cách hợp lý thành các hàm. Vì đây là tất cả trong một lớp có kết nối với tư cách là thành viên, nên việc tạo con trỏ trong mỗi chức năng sẽ thuận tiện hơn rất nhiều. Tuy nhiên, tôi không chắc cách tạo con trỏ trong giao dịch hoạt động.

Về cơ bản, nếu các giao dịch là mỗi kết nối, tôi chỉ có thể tạo ra nhiều con trỏ đang hoạt động trong giao dịch. Nếu chúng là mỗi con trỏ, điều đó có nghĩa là tôi phải đưa con trỏ đi khắp nơi. Đó là cái gì

Tài liệu này không đề cập đến vấn đề này, mặc dù thực tế là bạn có thể gọi connection.commit()khiến tôi khá tự tin rằng kiểm soát giao dịch là trên mỗi kết nối.

Câu trả lời:


6

Giao dịch là mỗi phiên, tức là mỗi kết nối.

PostgreQuery không hỗ trợ tạm dừng và tiếp tục giao dịch, vì vậy psycopg2 không thể tạo ra chúng trên mỗi con trỏ trừ khi nó ngầm tạo ra các kết nối mới phía sau hậu trường.

Trong thực tế tôi không thấy các con trỏ của psycopg2 đặc biệt hữu ích. Họ có thể giữ lại các tập kết quả nếu bạn không sử dụng tìm nạp gia tăng từ máy chủ, nhưng tôi không thấy chúng tốt cho nhiều thứ khác.

Tại sao lại phát hành thủ công begincommitmặc dù, thay vì sử dụng các phương thức kết nối cho chúng?


AFICT từ tài liệu, toàn bộ mô hình "DB API" hoàn toàn không hỗ trợ các giao dịch rõ ràng.
Tên giả

1
@FakeName Bạn không cần phải rõ ràng begin. Nếu không có giao dịch nào được mở, một giao dịch mới sẽ được bắt đầu cho bạn. Bạn chỉ cần commitphân định các giao dịch. Vì vậy, có, mô hình DB-API không hỗ trợ các giao dịch rõ ràng.
Craig Ringer

1
Nếu api DB đang thực hiện nó một cách tự động mà không cần tôi chỉ đạo cụ thể để làm như vậy, thì đó thực sự là một sự khởi đầu ngầm . Và bên cạnh đó, điều đó không liên quan, vì (như tôi đã nêu trong câu hỏi), tôi đang sử dụng chế độ tự động, bởi vì tôi không muốn những BEGINtuyên bố tự động đó . Tôi không muốn psycopg2tạo một giao dịch mới cho mỗi giao dịch SELECT.
Tên giả

Về cơ bản, TL; DR tôi muốn biết phạm vi chính xác của tất cả các giao dịch đang diễn ra vì A. Tôi điên theo cách đó và B. nó giúp ích rất nhiều cho việc gỡ lỗi.
Tên giả

1
Tôi sẽ không ngạc nhiên khi thấy những con bọ kỳ lạ xuất hiện với điều này. AFAIK autocommit thực sự có nghĩa là tự động không phải là quản lý giao dịch thủ công. Nếu bạn thực sự muốn quản lý phạm vi giao dịch theo cách thủ công, một khoản bổ sung BEGINlà vô hại và sẽ bị PostgreQuery bỏ qua WARNING: there is already a transaction in progress.
Craig Ringer

1

Từ tài liệu psycopg2 :

Trong các giao dịch Psycopg được xử lý bởi lớp kết nối. Theo mặc định, lần đầu tiên một lệnh được gửi đến cơ sở dữ liệu (sử dụng một trong các con trỏ được tạo bởi kết nối), một giao dịch mới được tạo. Các lệnh cơ sở dữ liệu sau đây sẽ được thực thi trong ngữ cảnh của cùng một giao dịch - không chỉ các lệnh được tạo bởi con trỏ đầu tiên, mà cả các lệnh được phát hành bởi tất cả các con trỏ được tạo bởi cùng một kết nối. Nếu bất kỳ lệnh nào thất bại, giao dịch sẽ bị hủy bỏ và không có lệnh nào được thực hiện nữa cho đến khi có lệnh gọi phương thức rollback ().

Đồng thời, từ phiên bản 2.4.2, có autocommitthuộc tính (nhấn mạnh thêm):

Thuộc tính đọc / ghi: nếu True, không có giao dịch nào được xử lý bởi trình điều khiển và mọi câu lệnh được gửi đến phụ trợ đều có hiệu lực ngay lập tức; nếu False một giao dịch mới được bắt đầu tại lần thực hiện lệnh đầu tiên : các phương thức commit()hoặc rollback()phải được gọi thủ công để chấm dứt giao dịch.

Chế độ tự động rất hữu ích để thực thi các lệnh yêu cầu được chạy bên ngoài một giao dịch, chẳng hạn như CREATE DATABASEhoặc VACUUM.

Mặc định là False(cam kết thủ công) theo thông số kỹ thuật DBAPI.

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.