Apakah aman untuk membatalkan permintaan PostgreSQL ALTER TABLE yang menunggu di kunci?

10

Kami memulai ALTER TABLEkueri beberapa jam yang lalu dan hanya baru-baru ini menyadari (via pg_stat_activity) bahwa ia menunggu di kunci. Kami menemukan kueri lain yang menahan kunci di atas meja yang ingin kami ubah, dan tidak membiarkannya pergi.

Kueri kami adalah kueri "sederhana" (mengubah tipe data kolom), tetapi itu berjalan pada tabel besar.

Alih-alih membunuh proses yang menahan kunci, kami telah memutuskan kami lebih memilih untuk membunuh ALTER TABLE.

Kami tidak membungkus ALTER TABLEtransaksi.

Sejauh yang saya mengerti, fakta bahwa permintaan kami sedang menunggu kunci berarti selalu menunggu kunci, dan tidak pernah mengubah apa pun.

Apakah ini benar? Apakah aman bagi kami untuk langsung membatalkan ALTER TABLEpermintaan kami ? Atau mungkinkah kueri telah memodifikasi sesuatu dan membatalkannya akan membuat database kita dalam keadaan setengah jadi?

PS: Rencananya adalah membatalkannya menggunakan SELECT pg_cancel_backend(pid);. Jika ini adalah ide yang buruk, tolong beri tahu saya.

JMTyler
sumber
1
Seharusnya tidak masalah untuk membatalkan ALTER TABLE. PostgreSQL memiliki DDL transaksional, dan Anda harus dibiarkan dalam kondisi yang sama seolah-olah Anda belum menjalankan ALTER TABLE sama sekali.
Josh Kupershmidt
Jadi ketika Anda mengatakan bahwa PostgreSQL memiliki DDL transaksi, apakah itu berarti bahwa setiap permintaan perubahan skema pada dasarnya dijalankan di dalam suatu transaksi?
JMTyler
1
Dalam kasus Anda, ALTER TABLE adalah "pada dasarnya berlari di dalam suatu transaksi", karena Anda berkata "Kami tidak membungkus ALTER TABLE dalam sebuah transaksi.". Jika Anda ingin, Anda dapat menulis BEGIN; ALTER TABLE foo ...; ALTER TABLE bar ...; dll; MELAKUKAN; - itulah fitur pembunuh nyata PostgreSQL yang memiliki DDL transaksional. Tetapi untuk situasi langsung Anda, ya, ALTER TABLE sendiri dapat dibatalkan dengan aman dan akan diputar kembali seolah-olah itu tidak pernah terjadi.
Josh Kupershmidt
Terima kasih banyak atas balasan cepat Anda! Ini adalah informasi yang sangat bagus. Bisakah Anda mempostingnya sebagai jawaban agar saya dapat menandainya sebagai diterima?
JMTyler

Jawaban:

13

Sejauh yang saya mengerti, fakta bahwa permintaan kami sedang menunggu kunci berarti selalu menunggu kunci, dan tidak pernah mengubah apa pun.

Benar - jika Anda melihat bahwa pg_stat_activity.waiting adalah "benar" untuk ALTER TABLE, itu hampir pasti berarti bahwa ia dengan sabar menunggu kunci AKSES EKSKLUSIF pada tabel targetnya, dan pekerjaan nyata (menulis ulang meja jika perlu, mengubah katalog) , indeks pembangunan kembali, dll.) belum dimulai.

Apakah aman bagi kami untuk langsung membatalkan permintaan ALTER TABLE kami? Atau mungkinkah kueri telah memodifikasi sesuatu dan membatalkannya akan membuat database kita dalam keadaan setengah jadi?

Membatalkan pertanyaan (atau, yang setara, memutar kembali transaksi) di PostgreSQL tidak memiliki bahaya kerusakan basis data apa pun yang mungkin membuat Anda takut pada database lain tertentu (misalnya peringatan mengerikan di bagian bawah halaman ini). Itu sebabnya non-superuser, dalam versi terbaru, bebas untuk menggunakan pg_cancel_backend()dan pg_terminate_backend()untuk membunuh permintaan mereka sendiri yang berjalan di backend lainnya - mereka aman untuk digunakan tanpa khawatir tentang korupsi basis data. Bagaimanapun, PostgreSQL harus siap untuk menghadapi proses apa pun yang terbunuh misalnya SIGKILL dari pembunuh OOM, server shutdown, dll. Itulah gunanya log WAL .

Anda mungkin juga telah melihat bahwa di PostgreSQL, dimungkinkan untuk melakukan sebagian besar perintah DDL yang bersarang di dalam transaksi (multi-pernyataan), mis.

BEGIN;
ALTER TABLE foo ...;
ALTER TABLE bar ...;
-- more stuff
COMMIT; -- or ROLLBACK; if you've changed your mind

(luar biasa untuk memastikan bahwa migrasi skema masuk secara bersamaan atau tidak sama sekali.) Anda berkata, meskipun:

Kami tidak membungkus ALTER TABLEtransaksi.

Itu bagus untuk satu perintah - dari dokumen ,

PostgreSQL sebenarnya memperlakukan setiap pernyataan SQL sebagai dieksekusi dalam suatu transaksi. Jika Anda tidak mengeluarkan perintah BEGIN, maka setiap pernyataan individu memiliki BEGIN tersirat dan (jika berhasil) KOMIT membungkusnya. Sekelompok pernyataan yang dikelilingi oleh BEGIN dan COMMIT kadang-kadang disebut blok transaksi.

Jadi membatalkan itu ALTER TABLE, baik melalui pg_cancel_backend()atau Ctrl-C yang dikeluarkan dari prompt psql mengendalikan, akan memiliki efek yang sama seperti jika Anda telah melakukan

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(meskipun seperti yang Anda harapkan, membatalkan yang mahal ALTER TABLEdapat menyelamatkan database dari banyak penggilingan yang tidak perlu jika Anda hanya akan ROLLBACKmelakukannya.)

Josh Kupershmidt
sumber
5

Untuk menguraikan jawaban Josh yang benar dan luar biasa:

Apakah aman bagi kami untuk langsung membatalkan permintaan ALTER TABLE kami?

Iya.

Itu akan aman bahkan jika itu di tengah penulisan ulang tabel .

Jika Anda menginginkannya, Anda bisa mematikan seluruh server PostgreSQL, atau bahkan mesin yang dihidupkan, nyalakan kembali, dan semuanya akan baik-baik saja. DDL di PostgreSQL bersifat transaksional dan aman untuk macet.

Operasi DDL dicatat melalui WAL dan dijamin dapat dibatalkan atau diselesaikan setelah pemulihan setelah macet atau dibatalkan.

Craig Ringer
sumber
3
Hanya sebuah catatan tentang "Anda bisa mematikan seluruh server PostgreSQL, atau bahkan mesin yang dihidupkan, restart, dan semuanya akan baik-baik saja" - cukup benar selama Anda memiliki perangkat keras andal yang tidak berbohong tentang fsync , wiki.postgresql.org/wiki/R reliable_Writes
Josh Kupershmidt
2
@ JoshKupershmidt Tentu, tapi itu tidak spesifik untuk DDL. Jika Anda memiliki masalah sinkronisasi maka Anda tidak aman untuk semuanya .
Craig Ringer