Dmitriy Kononov
Konuşalımİletişim

Haberler ve analiz

ON DELETE CASCADE, shard'lar ve replikalar: veritabanında sonradan pişman olunan üç karar

PlanetScale bir haftada zincirleme silme, shard grupları ve Neki replikalarını yazdı. Hangisi tek sunucudaki veritabanını ilgilendiriyor ve ben nasıl tasarlıyorum.

PlanetScale bir haftada Postgres hakkında üç yazı çıkardı: ON DELETE CASCADE'e neden güvenilmemeli, shard'lar nasıl tasarlanır ve shard'lı Neki'de ne yeni. Otuz kişilik bir şirkete shard daha uzun süre gerekmeyecek. Ama zincirleme silme ve “neyi silinmiş sayacağız” sorusu her veritabanını ilgilendiriyor; tek bir sanal makinede duran ve talepleri, teklifleri ve müşterileri tutan veritabanını bile.

Neler yayımlandı

PlanetScale 21 Ekim'de ON DELETE CASCADE'e neden güvenmediğini açıkladı. Cazibesi belli: yabancı anahtarları tanımlarsınız, Postgres alt satırları kendisi siler. Sorunlar sonra geliyor. Büyük bir zincirleme silme, etkilenen bütün tablolarda kilit tutuyor; sütun ekleme gibi sıradan bir migrasyon onun arkasında kuyruğa giriyor ve bütün yeni sorguları peşinden sürüklüyor: onlarda bu, canlı ortamda yazmanın durmasıyla bitti. Büyük ortamlarda böyle bir DELETE tek işlemde yüzlerce gigabayt WAL yazıyordu. İndeksi olmayan yabancı anahtar, tek satırı silmeyi tablonun tamamını taramaya çeviriyor. Mantıksal replikasyonda ise abone zincirleme silmeleri çalıştırmıyor; kendi alt tablosu varsa orada tek bir hata bile olmadan yetim satırlar kalıyor. Cevapları: yumuşak silme. Satır deleted_at değeri alıyor, gerçek DELETE'ler ise sonra, paketler halinde, sakin saatlerde, örneğin 30 gün sonra çalışıyor.

23 Ekim'de aynı ekip Neki'de shard tasarımını ele aldı. Oradaki tasarım birimi shard group: anahtarı aynı şekilde hash'leyen tablolar, aynı customer_id değerine sahip satırları aynı shard'a koyuyor; müşterinin siparişleri, sipariş kalemleri ve adresleri hep yan yana. Ülke ve para birimi gibi referans listeleri reference table olarak tanımlanıp her shard'a kopyalanıyor. Katalog lower(sku) ile shard'lanabiliyor, böylece AB-1042 ve ab-1042 aynı yere düşüyor. Bir de uyarı: tek shard içindeki işlem Postgres semantiğini koruyor, iki shard'a yayılan işlemin ise atomik commit'i yok.

20 Ekim'de Neki güncellemeleri özetinde preview döneminin bir ayında neler eklediklerini yazdılar: shard'lar için salt okunur replikalar, ayda 50 dolardan başlayan ve 1/8 vCPU, 1 GB bellek ve 10 GB NVMe'ye kadar inen Metal düğümleri, Azure'da açılış, materialized view, LISTEN/NOTIFY ve cursor desteği; COPY TO STDOUT artık shard'lı tablolarda çalışıyor, yani pg_dump veriyi okuyabiliyor. Dağıtık INSERT ... SELECT, dediklerine göre preview başlangıcına kıyasla yaklaşık 76 kat hızlandı.

İşletme için ne anlama geliyor

Araç kiralamayı ele alalım. Yönetici bir müşteriyi siliyor; müşteri istediği için ya da yanlışlıkla. Veritabanında zincirleme silme açıksa müşteriyle birlikte rezervasyonları, teslim tutanakları, imzaları ve kontrol fotoğrafları da gidiyor. Bir ay sonra hasar anlaşmazlığı geliyor ve kanıt yok. Zincirleme silme yoksa ve “silindi” işareti varsa müşteri listelerde görünmüyor, ama geçmiş sağlam ve karar 30 gün içinde geri alınabiliyor.

Sonuç: iş sisteminde silme, geri alınabilen bir durum olmalı. Shard'lar ve replikalar ise tek makine yetmemeye başladığında gerekir; çoğu şirket o noktadan çok uzak. Yabancı anahtarında indeks olmayan veritabanına, tek sunucuya sığmayan veritabanından çok daha sık rastlıyorum.

Bende nasıl çalışıyor

Projelerimin neredeyse hepsinde MariaDB var ve zincirleme silmeyi açmamayı tercih ediyorum: ilişkiler tanımlı, neyin silinmiş sayılacağına ise sunucudaki mantık karar veriyor.

Bir üretim şirketinde ürün listesinde on binlerce kalem var; parça ve malzeme hesaplama programı bunları 1C ile karşılaştırıyor. Kalem listede yoksa, spesifikasyonu ya da dokümantasyon dosyası eksikse program bunu sessizce geçmiyor: işaret sonuçta görünüyor. PlanetScale yazısındaki yetim satır hikâyesinin aynısı, kurallar düzeyinde çözülmüş hali. Program bir siparişi ortalama 65 saniyede işliyor, eskiden bu 4-5 saat sürüyordu ve bunun için shard gerekmedi.

ABD'deki PDR şirketinde 2023'te hız ve tek veri formatı için Google E-Tablolar'dan SQL veritabanına geçmeyi önerdim. Fikir kabul gördü; MariaDB'ye geçtikten sonra servisleri tek tek bağladık: belge parser'ları, telefon sistemi, leaderboard. Orada her arama kaydediliyor ve her gerçek lead huniyi sonuna kadar geçiyor; dönüşüm %30 arttı. Böyle bir şeyi zincirleme silme üzerine kurmazdım: arama kaydı ve belgeleriyle birlikte lead, anlaşma kapansa ya da müşteri gitse bile sonra raporlar için gerekiyor.

Neki'yi ve shard gruplarını kendim denemedim: hiçbir müşterimin verisi, Google Cloud'daki Debian üzerinde tek bir veritabanının yetmediği seviyeye çıkmadı.

Ben ne yapardım

Veritabanında ON DELETE CASCADE var mı diye bakın. Varsa tek bir satırın peşinden silinecek tablo zincirini yazıp işletme sahibine gösterin. Zincirleme silme genelde bu noktada kapatılır.

Müşteriler, siparişler ve belgeler için yumuşak silme getirin: deleted_at alanı ve sorgularda filtre. Fiziksel temizliği ayrı bir görev olarak, paketler halinde, mesai dışı saatlerde çalıştırın.

Yabancı anahtarlardaki indeksleri kontrol edin. Tek bir komut ve çoğu zaman yavaş veritabanının en ucuz tamiri.

Tek makine yettiği sürece shard'ı düşünmeyin. Yetmemeye başlarsa önce raporlar için okuma replikası; shard grupları konuşması ancak ondan sonra.

Sunucunun sistemin kurallarını ve durumunu nasıl tuttuğunu Sunucu: veri, erişim ve sürecin yürütülmesi yazısında anlattım. Hizmet alanları: iç sistemler ve Python ile veri işleme. Projeler: üretim için sipariş hesaplama ve PDR şirketinin teknik ortağı. Aynı konuda: korkmadan şema migrasyonu ve hiç geri yüklenmemiş yedek. Daha önce ağır sorgular ve veritabanındaki büyük değerler hakkında yazmıştım. Veritabanınızda bir şeyler zincirleme siliniyorsa ve tam olarak ne olduğundan emin değilseniz nasıl kurulu olduğunu anlatın: Görevi konuşalım.