Kilit bekleyen bir PostgreSQL ALTER TABLE sorgusunu iptal etmek güvenli midir?


10

Birkaç ALTER TABLEsaat önce bir sorgu başlattık ve kısa bir süre önce pg_stat_activitybir kilit beklediğini fark ettik . Değiştirmek istediğimiz masaya bir kilit tutan diğer sorguyu keşfettik ve gitmesine izin vermedik.

Sorgumuz "basit" bir sorgu (bir sütun veri türünü değiştirerek), ancak büyük bir tabloda çalışıyor.

Kilidi tutan işlemi öldürmektense, öldürmeyi tercih ettiğimize karar verdik ALTER TABLE.

Biz did not sarın ALTER TABLEbir işlemdeki.

Anladığım kadarıyla, sorgumuzun bir kilit beklemesi , her zaman bir kilit beklediği anlamına geliyor ve hiçbir şey değiştirmedi.

Bu doğru mu? ALTER TABLESorguyu açıkça iptal etmemiz güvenli midir? Veya sorgunun zaten bir şeyi değiştirmiş olması ve onu iptal etmesi veritabanımızı bir tür yarı yolda bırakabilir mi?

Not: Plan, kullanarak iptal etmektir SELECT pg_cancel_backend(pid);. Bu kötü bir fikirse lütfen bana bildirin.


1
ALTER TABLOSUNU iptal etmek için iyi olmalı. PostgreSQL'in işlemsel DDL'si vardır ve ALTER TABLE'ı hiç çalıştırmamış gibi bırakmanız gerekir.
Josh Kupershmidt

PostgreSQL'in DDL işlemi olduğunu söylediğinizde, şema değiştiren herhangi bir sorgunun aslında bir işlemin içinde olduğu anlamına mı geliyor?
JMTyler

1
Sizin durumunuzda, "ALTER TABLE'ı bir işlemde sarmadık." Eğer isterseniz, BEGIN yazabilirsiniz; ALTER MASA foo ...; ALTER TABLE çubuğu ...; vb. ; COMMIT; - işlemsel DDL'ye sahip PostgreSQL'in gerçek katil özelliği budur. Ancak acil durumunuz için, evet, ALTER TABLE kendi başına güvenli bir şekilde iptal edilebilir ve hiç olmamış gibi geri alınır.
Josh Kupershmidt

Hızlı yanıtlarınız için çok teşekkür ederim! Bu çok iyi bir bilgi. Kabul edilmiş olarak işaretleyebilmem için cevap olarak gönderebilir misiniz?
JMTyler

Yanıtlar:


13

Anladığım kadarıyla, sorgumuzun bir kilit beklemesi, her zaman bir kilit beklediği anlamına geliyor ve hiçbir şey değiştirmedi.

Doğru - pg_stat_activity.waiting'in bir ALTER TABLE için "true" olduğunu görürseniz, neredeyse kesinlikle hedef tablosunda ACCESS EXCLUSIVE kilidini ve gerçek çalışmasını sabırla beklediği anlamına gelir (gerekirse tabloyu yeniden yazma, katalogları değiştirme , yeniden oluşturma dizinleri vb.) henüz başlamadı.

ALTER TABLE sorguyu açıkça iptal etmemiz güvenli midir? Veya sorgunun zaten bir şeyi değiştirmiş olması ve onu iptal etmesi veritabanımızı bir tür yarı yolda bırakabilir mi?

PostgreSQL'de sorguları iptal etmek (veya aynı şekilde bir işlemi geri almak), diğer bazı veritabanlarında (örneğin bu sayfanın altındaki korkunç uyarı) ürkmüş olabileceğiniz herhangi bir veritabanı bozulması tehlikesine sahip değildir . Bu nedenle süper kullanıcı olmayanlar, son sürümlerde, diğer arka uçlarda çalışan kendi sorgularını kullanmakta pg_cancel_backend()ve pg_terminate_backend()öldürmekte serbesttirler - veritabanı bozulması hakkında endişelenmeden kullanmak güvenlidir. Sonuçta, PostgreSQL en neyi Yani vb OOM katil, sunucu kapatma, örn SIGKILL kapalı öldürülme herhangi süreci ile başa çıkmak için hazır olmak zorunda WAL günlüğü içindir.

PostgreSQL'de, bir (çoklu ifade) işleminin içine yerleştirilmiş DDL komutlarının çoğunu gerçekleştirmenin de mümkün olduğunu görmüş olabilirsiniz, ör.

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

(şema geçişlerinin ya hep birlikte ya da hiç gitmediğinden emin olmak için harika.)

Biz did not sarın ALTER TABLEbir işlemdeki.

Tek bir komut için bu iyi - dokümanlardan ,

PostgreSQL aslında her SQL deyimini bir işlem içinde yürütülüyor olarak ele alır. Bir BEGIN komutu vermezseniz, her bir ifadenin üstü kapalı bir BEGIN vardır ve (başarılıysa) COMMIT'in etrafına sarılır. BEGIN ve COMMIT ile çevrili bir ifade grubuna bazen işlem bloğu denir.

Dolayısıyla , kontrol eden psql isteminden verilen bir Ctrl-C'nin iptal edilmesi ALTER TABLE, pg_cancel_backend()yaptığınız gibi benzer bir etkiye sahip olacaktır.

BEGIN;
ALTER TABLE ... ;
ROLLBACK;

(umarım görebileceğiniz gibi, pahalı ALTER TABLEolanı iptal etmek , veritabanını ROLLBACKzaten gereksiz yere taşıyorsanız çok fazla gereksiz öğütmeden kurtarabilir .)


5

Josh'un doğru ve mükemmel cevabını detaylandırmak için:

ALTER TABLE sorguyu açıkça iptal etmemiz güvenli midir?

Evet.

Tabloyu yeniden yazmanın ortasında olsa bile güvenli olurdu .

İsterseniz tüm PostgreSQL sunucusunu veya aslında çalıştığı makineyi kapatabilir, yeniden başlatabilirsiniz ve her şey iyi olurdu. PostgreSQL'deki DDL işlemsel ve kilitlenmeye karşı güvenlidir.

DDL işlemleri WAL aracılığıyla günlüğe kaydedilir ve bir çökme veya iptal sonrasında kurtarma işleminden sonra geri alınabilecekleri veya tamamlanabilecekleri garanti edilir.


3
"Tüm PostgreSQL sunucusunu veya aslında çalıştığı makineyi kapatabilir, yeniden başlatabilir ve her şey yoluna girebilir" hakkında bir not - fsync hakkında yalanlamayan güvenilir bir donanıma sahip olduğunuz sürece oldukça doğru , wiki.postgresql.org/wiki/Reliable_Writes
Josh Kupershmidt

2
@JoshKupershmidt Elbette, ancak bu DDL'ye özgü değil. Senkronizasyon sorunlarınız varsa, her şey için güvenli değilsiniz .
Craig Ringer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.