Lewati ke isi

Cadangan dan jendela pemulihan

Riwayat sebuah target adalah rantai: cadangan penuh sesuai jadwal, dan di antaranya aliran perubahan yang berkelanjutan (WAL Postgres, binlog MySQL). Detik mana pun yang tercakup oleh sebuah cadangan penuh dan perubahan sesudahnya dapat dipulihkan. Rentang itu adalah jendela point-in-time.

gantt
  dateFormat  YYYY-MM-DD HH:mm
  axisFormat  %a %d
  section Full backups
  daily full      :milestone, 2026-10-01 02:07, 0d
  daily full      :milestone, 2026-10-02 02:07, 0d
  daily full      :milestone, 2026-10-03 02:07, 0d
  daily full      :milestone, 2026-10-04 02:07, 0d
  section Change stream
  WAL / binlog segments :active, 2026-10-01 02:07, 2026-10-04 18:00

Cadangan penuh

Mesin Mode Alat Pemulihan
Postgres 15–17 physical (bawaan) pg_basebackup -Ft -X fetch melalui protokol replikasi cadangan dasar + pemutaran ulang WAL sampai ke detiknya
Postgres 15–17 logical pg_dump -Fc, satu objek per basis data; pengecualian tabel dan ekspor selektif pg_restore, ditambah pemutaran ulang WAL melalui rantai fisik jika ada
MySQL 8.4 logical mysqldump --single-transaction --source-data=2 (routine, event, trigger) pemuatan + pemutaran ulang binlog sampai ke detiknya

Setiap cadangan mencatat inventaris: basis data, tabel, kolom, indeks, perkiraan baris dan ukuran, serta versi migrasi jika ada tabel migrasi. Itulah yang dibandingkan oleh konsol dan tenax diff.

Aliran perubahan

Setiap target dengan pemulihan point-in-time memiliki satu streamer:

  • Postgres: penerima WAL milik Tenax sendiri pada physical replication slot (ADR 0005). Slot tersebut menjamin tidak ada WAL yang hilang saat streamer dimulai ulang.
  • MySQL: mysqlbinlog --read-from-remote-server --raw --stop-never dari posisi binlog cadangan penuh terakhir.

Segmen diunggah begitu selesai, dan segmen yang masih ditulis diunggah setiap partialInterval (bawaan 60 detik), sehingga menit terakhir pun dapat dipulihkan. Setiap segmen membawa ringkasan: commit, insert, update, dan delete per tabel, DDL, serta opsional pratinjau baris tersamar.

Jika aliran terputus (slot hilang, binlog terhapus), Tenax menandai rantai sebagai terputus, memberi peringatan (TenaxStreamChainBroken), memulai rantai baru, dan segera membuat cadangan penuh (alasan chain-restart). Jendela lama tetap dapat dipulihkan sampai titik putusnya.

Retensi

Cadangan penuh disimpan menurut tingkat; segmen hanya disimpan sejauh yang dibutuhkan jendela; garbage collection menghapus semua yang lain, tetapi tidak pernah yang disematkan.

Preset Jendela Harian Mingguan Bulanan Tahunan
prod 7 hari 14 8 12 5
dev 3 hari 7 4 3 0
critical 14 hari 30 12 24 7

Cadangan penuh pertama yang di-commit pada suatu hari menjadi cadangan harian hari itu; yang pertama dalam satu minggu ISO menjadi cadangan mingguannya; dan seterusnya. Satu cadangan bisa membawa beberapa tingkat; tidak ada yang disalin. Sematan (tenax pin <id> --reason …) menahan cadangan apa pun tingkatnya. GC menulis rencananya ke bucket sebelum menghapus, menghapus manifest sebelum data, dan membersihkan unggahan yatim dan tidak lengkap setelah satu hari.

Format penyimpanan

<store prefix>/<org>/<project>/<namespace>/<target>/
  full/<backup-id>/manifest.json            # written last: the commit marker
  full/<backup-id>/data/<database>.zst.age  # dumps or the base backup tar
  full/<backup-id>/inventory.json.zst.age   # also readable with the catalog key
  full/<backup-id>/tags.json                # tiers, pins, verification results
  stream/…/<segment>.zst.age                # WAL / binlog segments and their summaries
  stream/position.json                      # the streamer's confirmed position
  • Kompresi: zstd pada level kebijakan, sekali, sebelum enkripsi; aktif secara bawaan (ADR 0013). compression.algorithm: none menyimpan data apa adanya.
  • Enkripsi: setiap objek dienkripsi dengan age ke penerima store di sisi klien. Bucket tidak pernah melihat plaintext.
  • Integritas: ukuran dan SHA-256 setiap objek tercatat di manifest dan diverifikasi pada setiap pembacaan.
  • Commit: sebuah cadangan baru ada setelah manifest.json ditulis. Crash sebelum itu hanya meninggalkan objek yatim yang dihapus GC, tidak pernah cadangan yang tampak lengkap.

Pengendalian beban

Pencadangan tidak pernah bersaing secara membabi buta dengan produksi: slot per host, per target, dan global, batas bandwidth, prioritas, jitter pada jadwal, dan penjaga beban yang menunda cadangan penuh selama server memiliki terlalu banyak koneksi aktif, lag replikasi terlalu besar, atau transaksi yang berjalan lama. Semuanya diatur di BackupPolicy.