Apakah transaksi dalam PostgreSQL melalui `psycopg2` per-kursor atau per-koneksi?

10

Saya melakukan beberapa pekerjaan dengan PostgreSQL 9.3 menggunakan psycopg2API database.

Saya memiliki DB API yang diatur dalam level isolasi minimum (mode "autocommit"), dan saya mengelola transaksi saya sendiri secara langsung melalui SQL. Contoh:

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;")

Pada dasarnya, apakah transaksi yang dimulai oleh cur.execute("BEGIN;")terbatas hanya pada kursor itu, atau apakah untuk seluruh koneksi ( self.conn.cursor())?

Beberapa hal yang lebih kompleks yang saya lakukan melibatkan beberapa operasi basis data yang terpisah, yang secara logis saya uraikan menjadi beberapa fungsi. Karena ini semua ada di kelas yang memiliki koneksi sebagai anggota, itu jauh lebih nyaman untuk membuat kursor dalam setiap fungsi. Namun, saya tidak yakin bagaimana cara membuat kursor dalam suatu transaksi bekerja.

Pada dasarnya, jika transaksi adalah per-koneksi, saya hanya bisa membuat banyak kursor on-the-fly dalam transaksi. Jika mereka per kursor, itu berarti saya harus melewati kursor di mana-mana. Yang mana itu?

Dokumentasi tidak menyentuh ini, meskipun fakta bahwa Anda dapat menelepon connection.commit()membuat saya cukup yakin kontrol transaksi adalah per-koneksi.

Nama palsu
sumber

Jawaban:

7

Transaksi adalah per-sesi, yaitu per-koneksi.

PostgreSQL tidak mendukung penangguhan dan melanjutkan transaksi, jadi psycopg2 tidak dapat membuatnya per-kursor kecuali secara implisit menciptakan koneksi baru di belakang layar.

Dalam prakteknya saya tidak menemukan kursor psycopg2 sangat berguna. Mereka dapat mempertahankan set hasil jika Anda tidak menggunakan pengambilan tambahan dari server, tetapi saya tidak menemukan mereka baik untuk banyak hal lain.

Mengapa masalah begindan commitmeskipun secara manual , daripada menggunakan metode koneksi untuk mereka?

Craig Ringer
sumber
AFICT dari dokumentasi, seluruh model "DB API" tidak benar-benar mendukung transaksi eksplisit sama sekali.
Nama Palsu
1
@FakeName Anda tidak perlu secara eksplisit begin. Jika tidak ada transaksi terbuka, yang baru dimulai untuk Anda. Anda hanya commitmenggambarkan transaksi. Jadi ya, model DB-API tidak mendukung transaksi eksplisit.
Craig Ringer
1
Jika DB api melakukannya secara otomatis tanpa saya secara khusus mengarahkannya, itu adalah awal yang tersirat . Dan selain itu, itu tidak relevan, karena (seperti yang saya sebutkan dalam pertanyaan), saya menggunakan mode autocommit, karena saya tidak inginBEGIN pernyataan otomatis itu . Saya tidak ingin psycopg2membuat transaksi baru untuk masing-masing SELECT.
Nama Palsu
TL; DR pada dasarnya saya ingin mengetahui ruang lingkup yang tepat dari semua transaksi yang terjadi karena A. Saya gila seperti itu, dan B. banyak membantu dengan debugging.
Nama Palsu
1
Saya tidak akan terkejut melihat bug aneh bermunculan dengan ini. AFAIK autocommit benar-benar dimaksudkan sebagai autocommit, bukan manajemen-transaksi manual. Jika Anda benar-benar ingin mengelola cakupan transaksi secara manual, tambahan BEGINtidak berbahaya dan hanya akan diabaikan oleh PostgreSQL WARNING: there is already a transaction in progress.
Craig Ringer
1

Dari dokumentasi psycopg2 :

Dalam Psycopg transaksi ditangani oleh kelas koneksi. Secara default, pertama kali sebuah perintah dikirim ke database (menggunakan salah satu kursor yang dibuat oleh koneksi), transaksi baru dibuat. Perintah basis data berikut ini akan dieksekusi dalam konteks transaksi yang sama - tidak hanya perintah yang dikeluarkan oleh kursor pertama, tetapi perintah yang dikeluarkan oleh semua kursor yang dibuat oleh koneksi yang sama. Jika ada perintah yang gagal, transaksi akan dibatalkan dan tidak ada perintah lebih lanjut yang akan dieksekusi sampai metode panggilan ke rollback ().

Pada saat yang sama, dari versi 2.4.2, ada autocommitatribut (penekanan ditambahkan):

Atribut baca / tulis: jika True, tidak ada transaksi yang ditangani oleh pengemudi dan setiap pernyataan yang dikirim ke backend memiliki efek langsung; jika False transaksi baru dimulai pada pelaksanaan perintah pertama : metode commit()atau rollback()harus secara manual dipanggil untuk mengakhiri transaksi.

Mode autocommit berguna untuk mengeksekusi perintah yang perlu dijalankan di luar transaksi, seperti CREATE DATABASEatau VACUUM.

Standarnya adalah False(komit manual) sesuai spesifikasi DBAPI.

Stephen
sumber