Eşzamanlılık ve Kilitleme
Eşzamanlılık ve kilitleme mimarisi: Adlandırılmış kilitler (named locks) ve yarım kalan iş korumasının aynı tablolar üzerindeki çakışmaları nasıl engellediğini ele alır.
GoArchive tasarım gereği sıralı çalışır: Aynı kaynak tabloya dokunacak iki çalıştırma; görev adları, kök tabloları veya hedefleri ne olursa olsun hiçbir zaman birlikte çalışmaz.
Tablolarınızı Kilitlemeyen Kilitler
Bir çalıştırma, süresi boyunca her biri ayrı bir oturumda olmak üzere iki adlandırılmış kilit (named lock, GET_LOCK()) kümesi tutar. Yeni bir takip şemasında ise bunlardan önce kısa bir süreliğine üçüncü bir kilit alır. Bu kilitler sunucunun kilit kaydındaki adlardır, tablo kilidi değildir: GoArchive hiçbir zaman LOCK TABLES çalıştırmaz. Bir kilit adı hiçbir tabloyu veya satırı kilitlemez; bu nedenle uygulamanın okuma ve yazma işlemlerini engellemez. Yalnızca başka bir GoArchive çalıştırmasını durdurur.
Şema kilidi hedefte bulunur ve yalnızca bir çalıştırma yeni bir takip şeması oluştururken tutulur. Tabloları ve etiketi aynı anda tek bir çalıştırma oluşturur. Bu sırada başlayan başka bir çalıştırma 60 saniyeye kadar bekler, şemayı hazır bulur ve devam eder. Kilit 60 saniye sonra hâlâ tutuluyorsa çalıştırma başlamaz (çıkış kodu 4) ve kilidi tutan bağlantıyı belirtir.
Görev kilidi hedefte, takip tablolarının yanında bulunur. Aynı görevin ikinci bir çalıştırması reddedilir:
job "<name>" is already running: its advisory lock is held by another session (destination connection <id>).Görev ağacındaki her tablo için bir kilit (kök tablo dahil), çakışabilecek tüm çalıştırmaların ortak olarak kullandığı tek sunucu olan kaynakta tutulur. Ağacı, çalışan bir görevle bir tabloyu paylaşan çalıştırma herhangi bir işlem yapmadan önce reddedilir:
the source table <database>.<table> is in use by another GoArchive run (source connection <id>). Jobs whose tables overlap run one at a time; this run did nothing.Bu kural tüm görev türleri için ve hedeflerden bağımsız olarak geçerlidir: İki farklı hedefe arşivlenen aynı kaynak tablolar sırayla işlenir; aynı tabloları okuyan iki
copy-onlygörevi de sırayla çalışır.
Reddedilen bir çalıştırma 4 çıkış koduyla sonlanır ve hiçbir işlem yapmaz. Böylece zamanlayıcı daha sonra yeniden deneyebilir.
Yarım Kalan İş Koruması
Kilitler, aynı anda başka bir aktif çalıştırmanın başlatılmasını engeller. Koruma mekanizması (guard) ise günlüğünde iş bırakarak durmuş bir görevi (çökme, hata veya kurtarma sırasında durdurma), kendi yeniden çalıştırması bu işi bitirene kadar korur. Her iki kilit kümesi de tutulurken, aynı takip merkezindeki (registry) başka bir görev aşağıdaki koşulların tümünü sağlıyorsa çalıştırma herhangi bir işlem yapmadan reddedilir:
- Aynı kaynak veri üzerinde çalışıyorsa;
- Ağacındaki bir tabloyu bu çalıştırmanın ağacıyla paylaşıyorsa;
- Görev çalışıyor olarak işaretlenmişse veya durumundan bağımsız olarak günlüğünde yarım kalmış (
copiedya dadeleting) kök kayıtlar barındırıyorsa.
Aynı kaynak veri şunları kapsar:
- Bu sunucunun verisi;
- İşlemleri (transactions) bu sunucunun
gtid_executedkümesinde bulunan bir sunucunun verisi: Birincil sunucuya yükseltilmiş bir replika, bir klon veya bu kaynağın replikasyonla veri aldığı bir sunucu; - Sunucunun bunu ayırt edemediği durumlarda, kayıt tablosunda aynı adı taşıyan tüm sunucu veritabanları tek bir veri olarak sayılır:
gtid_modedeğeriONolmadığında, bir Group Replication üyesinde ve birbirinden türetilerek oluşturulmuş parçalarda (shard). Bu tür her kaynak sunucuya kendijob_schemadeğerini atayın (Veritabanı Bağlantıları ).
Ret mesajı, her görevi durumuyla ve paylaştığı tablolarla birlikte listeler ve çıkış yolunu gösterir: O görevi yeniden çalıştırın, böylece kurtarma süreci yarım kalan işi tamamlasın. Mesajda adı geçen tüm görevler canlıyken (çalışıyor olarak işaretli ve son 60 saniye içinde canlılık sinyali vermiş) çalıştırma 4 çıkış koduyla, aksi halde 1 çıkış koduyla sonlanır: Durmuş bir görevin işi, o görevin yeniden çalıştırılmasını bekler.
Çalışıyor olarak işaretli olan, günlüğünde hiçbir kayıt bulunmayan ve süreci artık mevcut olmayan bir görev elle temizlenir (Takip Tablolarının Bakımı ).
Kilidi Tutan Oturumu Bulma
Her kilit adı bir önek ve bir özetten (hash) oluşur; bu sayede her tablo veya görev adı bu yapıya sığar. Sunucu aynı adları hesaplayabildiği için kilidi tutan oturumu SQL ile bulabilirsiniz:
-- job_schema içindeki job_name görevinin görev kilidi (hedefte çalıştırın)
SELECT IS_USED_LOCK(CONCAT('goarchive:j:', LEFT(SHA2(CONCAT(LOWER('<job_schema>'), CHAR(0), LOWER('<job_name>')), 256), 32)));
-- database.table üzerindeki kilit (kaynakta çalıştırın)
SELECT IS_USED_LOCK(CONCAT('goarchive:t:', LEFT(SHA2(CONCAT(LOWER('<database>'), CHAR(0), LOWER('<table>')), 256), 32)));
-- yeni bir takip şemasının şema kilidi (hedefte çalıştırın)
SELECT IS_USED_LOCK(CONCAT('goarchive:s:', LEFT(SHA2(CONCAT(LOWER('<job_schema>'), CHAR(0), LOWER('')), 256), 32)));
Sonuç, kilidi tutan bağlantının kimliğidir (connection id); kilit boştaysa NULL döner. Bir çalıştırma ayrıca her kilidi, temsil ettiği görev veya tabloyla birlikte debug seviyesinde günlüğe yazar. Kilitler herhangi bir yetki gerektirmez.
Canlılık Sinyali ve Kilit Oturumları
| Ayar | Değer |
|---|---|
| Canlılık sinyali (heartbeat) yazma aralığı | 15 saniye |
| Güncelliğini yitirme (staleness) eşiği | 60 saniye |
| Çalıştırmayı durduran ardışık canlılık sinyali hatası sayısı | 3 |
| Kilit sahipliği kontrolü, her kilit kümesi için | 30 saniye ve her commit öncesinde |
Kilit oturumu wait_timeout değeri | 300 saniye |
| Şema kilidi bekleme süresi, yeni takip şeması | 60 saniye |
Bir çalıştırma her 30 saniyede bir ve commit ettiği her veritabanı işleminden önce, kendi oturumlarının her iki kilit kümesini de hâlâ tuttuğunu kontrol eder. Kilit kümelerinden biri kaybedilirse çalıştırma durur ve işlenmekte olan veritabanı işlemi geri alınır: GoArchive kilitleri olmadan hiçbir kopyalamayı, silmeyi veya günlük yazımını commit etmez.
GoArchive süreci sonlanırsa, sunucu kilitlerini anında serbest bırakır. Sürecin çalıştığı makine veya ağ bağlantısı kaybedilirse, sunucu kilitleri 5 dakika içinde serbest bırakır: Bu süre dolmadan başlatılan bir çalıştırma anında reddedilir; süre dolduktan sonraki ilk başlatma ise başarılı olur.
Bir çalıştırma en az iki kaynak bağlantısına ve üç hedef bağlantısına ihtiyaç duyar (max_connections).
Korumanın Sınırları
- Korumayla tespit edilemeyen durumlar: Durdurulmuş bir görevin verilerini yalnızca bir GTID geçişi öncesinde almış sunucular ile bir grubun verisini barındıran ancak grubun dışında kalan bağımsız sunucular tespit edilemez. Başka bir görev bu tablolar üzerinde çalışmadan önce durmuş görevi yeniden bağlayın .
- Korumayla tespit edilemeyen durumlar: Kaynak veritabanının bir replikasında durdurulmuş olarak kayıtlı görevler tespit edilemez.
- Tek kayıt tablosu: Başka bir
job_schemaiçinde takip edilen durmuş bir görev engel oluşturmaz. - Bağlantı başına tek arka uç sunucu: Kilitler tek bir sunucuda bulunur. Bu nedenle okuma/yazma ayrıştırması yapan bir proxy, silme işlemleri birincil sunucuya giderken kilitleri bir replikaya yönlendirebilir. Her bağlantı, çalıştırma boyunca tek bir arka uç sunucuya (backend) ulaşmalıdır.
- Çoklu birincil (multi-primary) modda Group Replication: Kilitler bir üyeye özeldir; bu nedenle farklı üyelere bağlanan çalıştırmalar sıraya alınmaz.
