PostgreSQL Antipatterns: "ölü" ordularıyla savaşmak

PostgreSQL'in iç mekanizmalarının özellikleri onun bazı durumlarda çok hızlı olmasına, bazı durumlarda ise "çok hızlı olmamasına" olanak tanır. Bugün bir DBMS'nin nasıl çalıştığı ile geliştiricinin onunla ne yaptığı arasındaki çatışmanın klasik bir örneğine odaklanacağız. GÜNCELLEME ve MVCC ilkeleri.

Kısa hikaye harika makale:

Bir satır UPDATE komutuyla değiştirildiğinde aslında iki işlem gerçekleştirilir: DELETE ve INSERT. İÇİNDE dizenin geçerli sürümü xmax, GÜNCELLEME'yi gerçekleştiren işlemin sayısına eşit olarak ayarlanır. Daha sonra yaratılıyor yeni bir versiyon aynı satır; xmin değeri önceki sürümün xmax değeriyle örtüşüyor.

Bu işlem tamamlandıktan bir süre sonra duruma göre eski veya yeni versiyon COMMIT/ROOLBACK, tanınacak "ölü" (ölü demetler) geçerken VACUUM tabloya göre ve temizlendi.

PostgreSQL Antipatterns: "ölü" ordularıyla savaşmak

Ancak bu hemen olmayacak, ancak "ölü" ile ilgili sorunlar çok hızlı bir şekilde - tekrarlanarak veya tekrarlanarak - elde edilebilir. kayıtların toplu güncellenmesi büyük bir masada ve biraz sonra aynı durumla karşılaşacaksınız VAKUM yardımcı olamayacak.

#1: Hareket Ettirmeyi Seviyorum

Diyelim ki yönteminiz iş mantığı üzerinde çalışıyor ve aniden bazı kayıtlardaki X alanını güncellemenin gerekli olacağını fark ediyor:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Daha sonra, yürütme ilerledikçe Y alanının da güncellenmesi gerektiği ortaya çıkıyor:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... ve ayrıca Z - neden önemsiz şeylerle zaman kaybedesiniz ki?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

Şu anda veritabanımızda bu kaydın kaç versiyonu var? Evet, 4 parça! Bunlardan biri konuyla ilgilidir ve 3 tanesinin sizden sonra [otomatik]VACUUM tarafından temizlenmesi gerekecektir.

Bu şekilde yapmayın! Kullanmak tek istekte tüm alanları güncelleme — neredeyse her zaman yöntemin mantığı şu şekilde değiştirilebilir:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

#2: Kullanım Luke'tan farklı!

Yani hâlâ istiyordun bir tablodaki çok sayıda kaydı güncelleme (örneğin bir komut dosyası veya dönüştürücü kullanımı sırasında). Ve bunun gibi bir şey senaryoya giriyor:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Yaklaşık olarak bu formdaki bir talep oldukça sık meydana gelir ve neredeyse her zaman boş bir yeni alanı doldurmak için değil, verilerdeki bazı hataları düzeltmek için yapılır. Aynı zamanda kendisi de Mevcut verilerin doğruluğu hiçbir şekilde dikkate alınmaz - ama boşuna! Yani, tam olarak isteneni içerse bile kayıt yeniden yazılıyor - ama neden? Hadi düzeltelim:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Pek çok kişi bu kadar harika bir operatörün varlığından haberdar değil, bu yüzden burada bir kopya sayfası var. IS DISTINCT FROM ve yardımcı olacak diğer mantıksal operatörler:
PostgreSQL Antipatterns: "ölü" ordularıyla savaşmak
... ve karmaşık operasyonlar hakkında biraz ROW()-ifade:
PostgreSQL Antipatterns: "ölü" ordularıyla savaşmak

#3: Sevgilimi engelleyerek tanırım

başlatılıyor iki özdeş paralel süreç, her biri girişi "devam ediyor" olarak işaretlemeye çalışır:

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Bu işlemler aslında birbirinden bağımsız işler yapsalar bile aynı ID içerisinde, ilk işlem tamamlanana kadar ikinci istemci bu istek üzerine "kilitlenecektir".

Karar 1: görev bir öncekine indirgenir

Tekrar ekleyelim IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Bu formda, ikinci istek veritabanındaki hiçbir şeyi değiştirmeyecek, her şey zaten olması gerektiği gibi - bu nedenle engelleme gerçekleşmeyecek. Daha sonra uygulanan algoritmada kaydın “bulunamaması” olgusunu işliyoruz.

Karar 2: danışma kilitleri

Hakkında okuyabileceğiniz ayrı bir makale için büyük bir konu uygulama yöntemleri ve tavsiye niteliğindeki engellemenin "tarafı".

Karar 3: aptal aramalar

Ama bu tam olarak senin başına gelmesi gereken şey aynı kayıtla eş zamanlı çalışma? Yoksa örneğin müşteri tarafında iş mantığını çağırmak için kullanılan algoritmaları mı karıştırdınız? Peki ya düşünürsen?..

Kaynak: habr.com

Yorum ekle