Takip Tablolarının Bakımı
Takip tablolarını inceleyin, güvenle budayın, yarım kalan işten vazgeçin veya görevi yeniden bağlayın, bir görevi kullanımdan kaldırın ve çalışıyor durumunda kalmış bir görevi temizleyin.
Bu sayfadaki tüm bakım işlemleri bir DBA’nın işidir ve bir DBA hesabıyla yapılır: GoArchive’ın kendi hesabının takip şemasında DELETE veya DROP yetkisi yoktur. Örneklerde goarchive adlı bir job_schema ve 42 numaralı görev kimliği kullanılmıştır; bunları kendi değerlerinizle değiştirin.
İnceleme Sorguları
Tüm görevler
SELECT id, job_name, root_table, job_type, job_status,
TIMESTAMPDIFF(SECOND, last_heartbeat_at, UTC_TIMESTAMP()) AS heartbeat_age_sec
FROM goarchive.archiver_job
ORDER BY id;
Çalışan bir görev var mı? 60 saniyeden eski bir canlılık sinyali güncelliğini yitirmiş (stale) kabul edilir.
SELECT job_name, root_table,
TIMESTAMPDIFF(SECOND, last_heartbeat_at, UTC_TIMESTAMP()) AS heartbeat_age_sec,
CASE WHEN last_heartbeat_at IS NULL
OR TIMESTAMPDIFF(SECOND, last_heartbeat_at, UTC_TIMESTAMP()) > 60
THEN 'STALE' ELSE 'live' END AS liveness
FROM goarchive.archiver_job
WHERE job_status = 1;
Tek bir görev için durum dağılımı
SELECT ga_status,
CASE ga_status WHEN 1 THEN 'copied' WHEN 2 THEN 'completed' WHEN 4 THEN 'deleting' END AS name,
COUNT(*) AS roots
FROM goarchive.archiver_job_log_42
GROUP BY ga_status;
Bir sonraki çalıştırmanın yeniden işleyeceği kök kayıtlar (archive: 1; purge: 4)
SELECT * FROM goarchive.archiver_job_log_42 WHERE ga_status IN (1, 4) ORDER BY k1;
Görevin bağlama bilgisi (binding)
SELECT source_server_uuid, source_database, destination_database, config_fingerprint, root_key_columns
FROM goarchive.archiver_job WHERE job_name = 'archive_old_orders';
Hangi Kayıtları Silmek Güvenlidir?
Sıfırıncı kural: Görev çalışırken takip tablolarına asla dokunmayın. job_status = 0 olduğunu ya da job_status = 1 iken canlılık sinyalinin güncelliğini yitirdiğini ve sürecin gerçekten sonlandığının doğrulandığını teyit edin (aşağıya bakın
).
| İşlem | Güvenli mi? | Koşul ve Sonuç |
|---|---|---|
DELETE … WHERE ga_status = 2 (archive, purge) | ✅ | Yalnızca denetim geçmişidir (audit history): Kontrol noktası (checkpoint) işlevi yoktur ve tamamlanan kök kayıtlar zaten kaynaktan silinmiştir |
DELETE … WHERE ga_status = 2 AND k1 = <v1> AND … AND kN = <vN> (tek kök kayıt; archive, purge) | ✅ | where aralığına geri dönen bir kök kaydı yeniden arşivlemek veya tasfiye etmek için kullanılır (hata mesajı bu kaydı belirtir): Yalnızca o kök kaydın günlük kaydı silinir. Tüm anahtar kolonlarını (k1…kN) kök anahtar sırasıyla belirtin: Daha az kolon belirtilirse ifade başka kök kayıtların günlük kayıtlarını da siler. Bileşik anahtarda (composite key) hata mesajı değerleri - ile birleştirir; her değeri kaynak satırdan alın |
DELETE … WHERE ga_status = 2 (copy-only) | ⚠️ | Bu kök kayıtlar artık resume: true tarafından atlanmaz; hedefteki satırları da silinmedikçe yeniden çalıştırma onları tekrar kopyalar ve yinelenen kayıtlar nedeniyle başarısız olur |
DELETE … WHERE ga_status IN (1, 4) | ⚠️ | Kurtarmadan vazgeçilmiş olur: Bkz. Günlükteki Kök Kayıtlardan Vazgeçme |
DROP TABLE archiver_job_log_<id> ve görev satırının DELETE ile silinmesi | ✅ yalnızca bekleyen iş yoksa | Görevi kullanımdan kaldırma
; copied veya deleting kök kayıtlar varken bu işlem vazgeçme anlamına gelir |
Yalnızca DROP TABLE archiver_job_log_<id> | ⚠️ | Bir sonraki çalıştırma tabloyu boş olarak yeniden oluşturur ve devam eder: archive ve purge kaydı kaybeder, copy-only resume atlamalarını kaybeder ve bekleyen kök kayıtlardan vazgeçilmiş olur |
TRUNCATE archiver_job | ❌ | AUTO_INCREMENT değerini sıfırlar: Yeni görevler eski günlüklerin kimliklerini alır ve eski günlüğü satır içeren bir görev, o günlük kaldırılana kadar kayıtsız kalır. Aynı bakım aralığında tüm günlük tablolarını da kaldırın veya DELETE kullanın |
Yalnızca DROP TABLE archiver_job | ❌ | archiver_job tablosu olmayan etiketli bir şema reddedilir: Aksi halde günlükler, kimliklerini yeniden kullanan yeni görevlerle karşılaşırdı |
Yalnızca DROP TABLE goarchive_meta | ❌ | Etiketi olmayan dolu bir archiver_job, etiket satırı geri yüklenene kadar reddedilir |
job_status = 1 iken ve canlılık sinyali güncelken herhangi bir işlem | ❌ | Görev canlıdır |
Tüm takip durumunu temizlemek için önce hiçbir günlüğün copied veya deleting kök kayıt içermediğini doğrulayın (aksi halde bu, söz konusu her görev için vazgeçme anlamına gelir). Ardından goarchive_meta, archiver_job ve tüm archiver_job_log_<id> tablolarını birlikte kaldırın. Büyük günlükleri parçalar halinde budayın (DELETE … WHERE ga_status = 2 LIMIT 50000 ifadesini tekrarlayarak). Kaydın uyumluluk (compliance) açısından değeri varsa önce dışa aktarın.
Günlükteki Kök Kayıtlardan Vazgeçme
Bekleyen kök kayıtlar yarıda kesilmiş işlerdir. copied durumundaki bir archive kök kaydının ağacı hedefte eksiksiz bulunur; kaynak satırlarının bir kısmı ise alt kayıtlardan başlanarak silinmiş olabilir. deleting durumundaki bir purge kök kaydı kısmen silinmiş olabilir. Bunları yalnızca günlük tamamlayabilir: Kurtarma süreci, where koşulundan bağımsız olarak her ağacı anahtarına göre yeniden keşfeder.
Bu kayıtları tamamlamayı tercih edin: Özgün yapılandırmayı veya kaynağı geri yükleyip görevi bir kez çalıştırın ya da yük devri sonrası görevi yeniden bağlayın . Bu kayıtlar tamamlanana veya bunlardan vazgeçilene kadar, ağacı bu görevin tablolarından birini paylaşan başka hiçbir görev aynı kaynak veri üzerinde çalışmaz.
Vazgeçmek, bu kök kayıtların günlük satırlarını silmek anlamına gelir. Böylece bir sonraki çalıştırma güncel yapılandırmaya bağlanır ve bu kayıtları hiçbir zaman tamamlamaz. Bunu yalnızca özgün yapılandırma veya kaynak artık mevcut değilse ve her iki sunucunun yedekleri alınmışsa yapın. Geride kalanları önce elle çözün:
| Görev Türü | Geride Kalanlar | Günlük Satırlarını Silmeden Önce Yapılacaklar |
|---|---|---|
archive (ga_status = 1) | Hedefteki eksiksiz ağaçlar; kaynakta her ağaçtan kalan satırlar | Hedefteki ağaçları koruyun: Kaynaktan önceden silinmiş alt kayıtların tek kopyası bu ağaçlarda olabilir. Hedefin bu satırları içerdiğini doğruladıktan sonra her kök kaydın kaynakta kalan satırlarını alt kayıtlardan başlayarak elle silin; ya da bu kök kayıtların yeniden okunması mükerrer kayıt hatasına (duplicate key) yol açacağından, ilgili kayıtları sonraki tüm where filtrelerinin kapsamı dışında tutun. |
purge (ga_status = 4) | Kaynakta her ağaçtan kalan satırlar | Bunları alt kayıtlardan başlayarak elle silin veya kalmalarını kabul edin; yeni yapılandırma bu satırları yalnızca where koşulu onları seçerse siler |
copy-only (ga_status = 2) | Kök kayıtların hedefteki kopyaları | Yeniden çalıştırma bunları tekrar kopyalar: Aynı hedefe kopyalarken yinelenen kayıtlar nedeniyle başarısız olur. Görevi boş bir hedefe yönlendirin veya kopyalanmış kök kayıtları where koşulunun dışında bırakın; yalnızca görev adını değiştirmek hiçbir şeyi değiştirmez |
Ardından, görev çalışmıyorken:
SELECT ga_status, COUNT(*) FROM goarchive.archiver_job_log_42 GROUP BY ga_status;
DELETE FROM goarchive.archiver_job_log_42 WHERE ga_status = 1; -- archive: copied
DELETE FROM goarchive.archiver_job_log_42 WHERE ga_status = 4; -- purge: deleting
DELETE FROM goarchive.archiver_job_log_42 WHERE ga_status = 2; -- copy-only: completed
Yük Devri (Failover) Sonrası Görevi Yeniden Bağlama
Bir kaynak yük devrinden (failover) sonra, birincil sunucuya yükseltilen sunucu aynı veriyi yeni bir server_uuid altında tutar. Bağlama kontrolü de bekleyen işi olan görevi reddeder. Aynı veri olduğunu doğruladıktan sonra görevi yeni sunucuya yönlendirin, ardından günlükteki işi tamamlamak için görevi yeniden çalıştırın:
-- Yeni kaynak sunucuda:
SELECT @@GLOBAL.server_uuid;
-- Hedefte, bu değerle:
UPDATE goarchive.archiver_job SET source_server_uuid = '<new server_uuid>'
WHERE job_name = 'archive_old_orders';
Bu bilinçli bir işlemdir: Aynı veriyi tutmayan bir kaynağa karşı günlüğün yeniden işlenmesi yanlış satırları siler veya atlar. Kimlik değerini birebir doğru yazın: Geçerli biçimde bir uuid olmayan değer görevin kendi çalıştırması tarafından reddedilir ve çakışan görevleri engellemeye devam eder.
Yeniden bağlama yapılana kadar, ağacı durmuş görevin tablolarını paylaşan diğer görevler yeni sunucuda da reddedilir. Bu, yeni sunucu eski sunucunun işlemlerini (transactions) içerdiğinde, gtid_mode = ON ile çalışmadığında veya bir Group Replication üyesi olduğunda geçerlidir. İki durum tespit edilmez ve bu tablolar üzerinde başka bir görev çalışmadan önce yeniden bağlama gerektirir: Veriyi yalnızca bir GTID geçişinden önce almış bir sunucu ve bir grubun verisini tutan ancak grubun dışında kalan bir sunucu.
Bir Görevi Tamamen Kullanımdan Kaldırma (Retire)
Bu işlem bir görevi ve tüm durum bilgisini kaldırır. Artık kullanmadığınız bir ad için ya da başka bir tür, kök tablo veya kök anahtar vermek istediğiniz bir ad için uygulanır. Bekleyen işi olan bir görev doğrudan kullanımdan kaldırılamaz: Günlüğünü kaldırmak, yarıda kesilmiş ağaçlarının tek kaydını da kaldırır.
-- 1. Görevin çalışmadığını doğrulayın.
SELECT job_name, job_status,
TIMESTAMPDIFF(SECOND, last_heartbeat_at, UTC_TIMESTAMP()) AS heartbeat_age_sec
FROM goarchive.archiver_job WHERE job_name = 'archive_old_orders';
-- 2. Bekleyen işi olmadığını doğrulayın: archive ve purge için sonuç 0 olmalıdır.
-- Aksi halde önce görevi tamamlayın veya bu işlemi vazgeçme olarak değerlendirin (yukarıda).
SELECT COUNT(*) FROM goarchive.archiver_job_log_42 WHERE ga_status IN (1, 4);
-- 3. Günlük tablosunu kaldırın (kimliği kendi değerinizle değiştirin).
DROP TABLE IF EXISTS goarchive.archiver_job_log_42;
-- 4. Görev satırını silin: Her zaman DELETE kullanın, asla TRUNCATE kullanmayın.
DELETE FROM goarchive.archiver_job WHERE job_name = 'archive_old_orders';
Aynı adla yeniden oluşturulan bir görev boş bir günlükle başlar. Bekleyen iş yoksa archive ve purge görevleri yalnızca kaydı kaybeder. Bir copy-only görevi ise resume atlamalarını kaybeder: Yeniden çalıştırma tüm kök kayıtları tekrar kopyalar ve bu kayıtları hâlâ içeren bir hedefte yinelenen kayıtlar nedeniyle başarısız olur.
Askıda / Çalışıyor Durumunda Kalmış (Stale) Bir Görevi Temizleme
Çöken bir çalıştırma, job_status = 1 değerini giderek eskiyen bir canlılık sinyaliyle bırakır. Bu görev ve durumu ne olursa olsun günlüğünde copied veya deleting kök kayıtlar bulunan her görev, ağacı kendi tablolarından birini paylaşan diğer görevlerin çalıştırmalarını reddeder:
engine: job "purge_logs" shares source tables in `shop` with jobs that are marked running or
stopped with unfinished work (registry `goarchive`.`archiver_job`). This run did nothing.
archive_old_orders: marked running, heartbeat 1h4m1s ago, unfinished roots in its log; shares payment_logs
Rerun each job with unfinished roots so that its recovery finishes them, then rerun this one. A job
that cannot be rerun (its source or config is gone): docs/README_JOBS_SCHEMA.md, "Abandoning logged roots".
A job marked running whose heartbeat stopped: confirm its process is gone first
(docs/README_JOBS_SCHEMA.md, "Clearing a stale running job").
Mesajda adı geçen belgeler, bu sayfadaki Günlükteki Kök Kayıtlardan Vazgeçme (“Abandoning logged roots”) ve Askıda / Çalışıyor Durumunda Kalmış (Stale) Bir Görevi Temizleme (“Clearing a stale running job”) bölümleridir.
Önce eski sürecin sonlandığını doğrulayın. Güncelliğini yitirmiş bir canlılık sinyali görev kilidini serbest bırakmaz; kilidi yalnızca sürecin veritabanı oturumunun kapanması serbest bırakır. Hedefte şu sorguyu çalıştırın:
SELECT IS_USED_LOCK(CONCAT('goarchive:j:', LEFT(SHA2(CONCAT(LOWER('<job_schema>'), CHAR(0), LOWER('<job_name>')), 256), 32)));
NULL sonucu, kilidi hiçbir oturumun tutmadığı anlamına gelir. Bir bağlantı kimliği (connection id) dönüyorsa oturum hâlâ canlıdır.
Ardından herhangi bir UPDATE yapmadan görevin kendisini yeniden çalıştırın: Kurtarma sürecini görevin günlüğü yönetir ve yarım kalan kök kayıtlar tamamlandığında görev kimseyi engellemez. Bir görevi yalnızca günlüğünde hiç copied veya deleting kök kayıt yoksa boşta olarak işaretleyin (UPDATE … SET job_status = 0 WHERE id = <id>): İşaretleme işi tamamlamaz ve günlük bu tür kök kayıtlar içerdiği sürece görev çakışan görevleri engellemeye devam eder. Günlük satırlarını silmeyin; bu, vazgeçme anlamına gelir.
Yedekler
- Takip tabloları InnoDB’dir ve işlemseldir (transactional). Bunları hedefin olağan yedeklerine dahil edin ve arşivlenen verilerle birlikte yedekleyin: Tanımladığı veriden farklı bir zamana ait olarak geri yüklenen bir günlük, kurtarma sürecini ve copy-only
resumedavranışını yanıltır. - Hedef verilerini takip tabloları olmadan geri yüklemek görevleri kayıtsız bırakır. Archive ve purge görevleri sıfırdan başlar; copy-only her şeyi yeniden kopyalar ve yinelenen kayıtlar nedeniyle başarısız olur.
- Ayrı bir
job_schema, takip durumunu arşivlenen verilerin yedeklerinin dışında tutar ve bu şemaya ayrıca yetki verilir.
