Apakah permintaan Postgres berjalan lama dibatalkan jika koneksi terputus / rusak?


20

Jika saya membuka koneksi ke Postgres dan mengeluarkan query yang sudah berjalan lama, dan kemudian memutuskan koneksi (mis., Bunuh proses klien yang membuka koneksi), apakah query yang sudah berjalan lama akan terus berjalan, atau akan dibatalkan secara otomatis? Apakah ini dapat dikonfigurasi?

(Saya menggunakan Postgresql 9.2.9)

Jawaban:


32

"Tergantung".

Jika klien lenyap karena kehilangan koneksi jaringan, permintaan biasanya akan berjalan sampai diambil cukup baris untuk mengisi buffer kirim jaringan, kemudian berhenti dan macet sampai koneksi TCP turun, pada titik mana ia akan dibatalkan. Jika selesai sebelum mengisi TCP send buffer, ia akan selesai dengan sukses, jadi jika itu otomatis, permintaan akan dikomit.

Jika klien terbunuh sedemikian rupa sehingga sistem operasi klien dapat melaporkan ke server melalui TCP RST (seperti segfault / crash klien, SIGTERM, SIGKILL, dll.), Server PostgreSQL akan menetapkan tanda bendera interupsi. Lain kali kueri memeriksa interupsi saat dijalankan akan melihat bendera dan batal. Kadang-kadang sebuah query mungkin melakukan pekerjaan yang sangat berat dalam kode yang tidak memeriksa gangguan - beberapa ekstensi, dan beberapa tempat di dalam inti PostgreSQL - dalam hal ini mungkin tidak melihat gangguan untuk waktu yang lama dan terus berjalan. Akan cukup selalu melihat interupsi dan batal sebelum menyelesaikan dan melakukan jika itu otomatis.

Jika klien terbunuh oleh sesuatu seperti reboot OS tiba-tiba, sehingga host klien tiba-tiba tidak tahu tentang koneksi TCP tetapi masih dapat merespon pada jaringan, permintaan mungkin akan dibatalkan ketika pertama kali mencoba menulis baris, seperti Jeff berkata, karena host klien akan mengirim TCP RST sebagai tanggapan terhadap paket pertama yang dikirim oleh server setelah reboot. PostgreSQL memeriksa interupsi pada setiap baris yang dikirim.

Perilaku ini tidak dapat dikonfigurasi. Sejauh menyangkut PostgreSQL jika klien pergi tugasnya adalah untuk mengakhiri setiap pertanyaan yang klien jalankan. Untuk mengubah itu, Anda akan memerlukan semacam token penyelesaian kueri yang bisa Anda peroleh di awal permintaan, kemudian gunakan untuk bertanya kepada server tentang permintaan tersebut melalui koneksi lain nanti. Pada dasarnya Anda harus menerapkan kueri asinkron / latar belakang. Mungkin fitur yang bagus, tetapi saat ini tidak didukung.

Jika kueri adalah komitmen otomatis, atau jika kueri Anda adalah COMMITyang sedang dalam penerbangan pada saat Anda membunuh klien / kehilangan koneksi, ada kemungkinan transaksi berada dalam kondisi tak tentu di mana klien tidak tahu apakah atau tidak berkomitmen. Tidak ada cara nyata untuk mengetahuinya, selain mencari efek transaksi pada data.

Jika itu tidak dapat diterima, Anda dapat menggunakan komit dua fase dan manajer transaksi sisi klien.


1
Wow, apa yang saya cari, jawaban terinci yang luar biasa! Terima kasih @Craig_Ringer!
Rob Bednark


2

Ini akan terus berjalan sampai mencoba mengembalikan baris ke koneksi dan mendeteksi kerusakan. Jadi untuk kueri yang melakukan semua pekerjaan sebelum mengembalikan baris, pada dasarnya akan berjalan sampai selesai.


Terima kasih @jjanes. Bisakah Anda menunjukkan dokumentasi atau kode sumber apa pun yang menunjukkan ini?
Rob Bednark
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.