Kesadaran operasional

Pemantauan basis data itu sendiri serta postur backup dan restore.

Daftar isi

Kesadaran operasional pada TimescaleDB mencakup pemantauan basis data itu sendiri, yaitu metadata chunk, kebijakan, dan statistik kompresi, serta postur backup dan restore yang menentukan ketahanan layanan terhadap kegagalan. Topik ini menjelaskan tampilan metadata yang disediakan TimescaleDB pada skema timescaledb_information, dua jalur backup utama yaitu pg_dump logis dan pg_basebackup fisik, serta Point-in-Time Recovery melalui arsip WAL. Setelah membaca topik ini, sebuah instance TimescaleDB yang sudah dilengkapi continuous aggregates, kompresi, dan retensi dapat dipantau dan dipulihkan dengan cara yang tidak bergantung pada satu jalur backup saja.

Apa yang dipantau pada TimescaleDB#

Pemantauan TimescaleDB berbeda dari pemantauan Postgres biasa karena adanya objek-objek ekstensi yang tidak terlihat pada katalog standar. Hypertable, chunk, continuous aggregate, dan kebijakan background worker adalah objek yang dipantau melalui tampilan pada skema timescaledb_information. Tampilan ini memberi jawaban atas pertanyaan operasional yang khas, misalnya berapa banyak chunk yang sudah dikompresi, kapan iterasi refresh terakhir dijalankan, dan berapa banyak baris yang sudah dihapus oleh kebijakan retensi. Tanpa tampilan ini, operator harus mengurai katalog internal _timescaledb_catalog secara manual, yang tidak praktis untuk pemantauan harian.

Pemantauan juga mencakup metrik Postgres yang sudah dikenal, yaitu penggunaan buffer, koneksi aktif, durasi query, dan ukuran tabel. Metrik ini tetap relevan pada TimescaleDB karena ekstensi tidak menggantikan mesin Postgres, melainkan menambah lapisan di atasnya. Alat seperti pg_stat_statements memberi visibilitas ke query yang lambat, sedangkan pg_stat_activity memberi visibilitas ke sesi yang sedang berjalan. Karena itu, pemantauan TimescaleDB sebaiknya dipikirkan sebagai pemantauan Postgres biasa yang diperluas dengan tampilan metadata ekstensi, bukan sebagai disiplin yang terpisah.

Metadata inti untuk pemantauan#

Tampilan timescaledb_information menyimpan metadata inti yang dibutuhkan operasi harian. Tampilan hypertables memberi daftar hypertable beserta ukurannya, tampilan chunks memberi daftar chunk beserta rentang waktu dan status kompresinya, sedangkan tampilan jobs memberi daftar pekerjaan latar belakang beserta jadwal dan hasil iterasi terakhir. Tampilan continuous_aggregates memberi daftar continuous aggregate beserta kebijakan refresh yang terpasang. Kueri terhadap tampilan-tampilan ini dapat digunakan untuk membangun dashboard operasional sederhana yang menjawab pertanyaan dasar, yaitu apakah kebijakan kompresi dan retensi berjalan sebagaimana mestinya. Perintah berikut tidak dijalankan di sandbox karena memerlukan Postgres dengan TimescaleDB aktif, sehingga hanya menjadi referensi sintaksis.

postgres Pemantauan metadata TimescaleDB
-- daftar hypertable dan ukurannya
SELECT hypertable_name, num_chunks,
       hypertable_size(format('%I.%I', hypertable_schema, hypertable_name)::regclass) AS size_bytes
FROM timescaledb_information.hypertables
ORDER BY size_bytes DESC;

-- status kompresi per chunk
SELECT chunk_name, compression_status,
       before_compression_total_bytes, after_compression_total_bytes
FROM chunk_compression_stats('suhu_sensor');

-- daftar pekerjaan latar belakang dan jadwalnya
SELECT j.job_id, j.application_name, j.proc_name,
       j.schedule_interval, s.last_run_status, j.next_start
FROM timescaledb_information.jobs j
LEFT JOIN timescaledb_information.job_stats s USING (job_id);

-- daftar continuous aggregate dan kebijakannya
SELECT view_name, materialized_only, compression_enabled
FROM timescaledb_information.continuous_aggregates;
text Keluaran
hypertable_name|num_chunks|size_bytes
cpu_node|1|81920
t1|1|57344
suhu_sensor|1|49152
telemetri|0|24576
chunk_name|compression_status|before_compression_total_bytes|after_compression_total_bytes
_hyper_89_179_chunk|Uncompressed||
job_id|application_name|proc_name|schedule_interval|last_run_status|next_start
3|Job History Log Retention Policy [3]|policy_job_stat_history_retention|1 mon|Success|2026-12-01 00:00:00+00
1|Telemetry Reporter [1]|policy_telemetry|24:00:00|Success|2026-11-08 14:48:49.151088+00
view_name|materialized_only|compression_enabled

pg_dump sebagai backup logis#

pg_dump adalah utilitas Postgres yang menghasilkan berkas berisi perintah SQL untuk merekonstruksi skema dan data. Berkas ini disebut backup logis, sebab isinya berupa teks SQL atau format biner kustom, bukan salinan blok fisik basis data. Backup logis cocok untuk migrasi antar versi Postgres, pemindahan sebagian skema, dan pengarsipan jangka panjang yang tidak bergantung pada arsitektur mesin sumber. Pada TimescaleDB, pg_dump juga menyertakan definisi hypertable, continuous aggregate, dan kebijakan, sehingga restore pada instance lain dapat membangun ulang seluruh struktur ekstensi.

Keterbatasan pg_dump adalah waktu restore yang tumbuh linier dengan ukuran data, sebab restore menjalankan kembali seluruh INSERT dan indeks harus dibangun ulang. Pada hypertable berisi puluhan gigabyte, restore dapat memerlukan waktu puluhan menit hingga beberapa jam, tergantung pada kecepatan disk dan jumlah indeks. Perintah berikut tidak dijalankan di sandbox karena memerlukan pg_dump yang tidak tersedia, sehingga hanya menjadi referensi sintaksis.

bash Backup logis dengan pg_dump
# tidak-dijalankan
# backup satu hypertable ke berkas format custom
pg_dump --format=custom --compress=9 \
    --table=suhu_sensor timescaledb_demo > backup.dump

# restore ke basis data lain (memerlukan basis data tujuan yang aktif)
# pg_restore -d timescaledb_demo_backup backup.dump

Perintah di atas menulis backup.dump di direktori kerja tanpa keluaran pada stdout. pg_restore membutuhkan basis data tujuan yang sudah dibuat, sehingga tidak dijalankan pada contoh ini.

Base backup dan Point-in-Time Recovery#

Backup fisik melalui pg_basebackup menghasilkan salinan blok-blok basis data apa adanya, sehingga restore menjadi operasi penyalinan berkas, bukan eksekusi SQL. Karena itu, restore dari base backup jauh lebih cepat daripada dari pg_dump, terutama pada basis data berukuran besar. Base backup juga menjadi titik awal Point-in-Time Recovery atau PITR, yaitu teknik pemulihan ke waktu tertentu dengan memutar ulang arsip WAL dari base backup hingga waktu target. PITR berguna ketika terjadi kesalahan logika, misalnya DROP TABLE yang tidak disengaja, sebab pemulihan dapat dihentikan tepat sebelum perintah itu dieksekusi.

PITR memerlukan tiga komponen, yaitu base backup, arsip WAL yang dikelola oleh archive_command, dan file konfigurasi recovery.signal yang menandai instance sebagai mode pemulihan. Arsip WAL sebaiknya disimpan pada media yang terpisah dari basis data utama, sebab WAL yang hilang membatasi PITR ke waktu sebelum arsip terputus. Pada TimescaleDB, WAL juga mencakup modifikasi internal ekstensi, sehingga arsip WAL lengkap diperlukan untuk pemulihan yang konsisten. Perintah berikut tidak dijalankan di sandbox dan hanya menjadi referensi sintaksis.

bash Base backup dan arsip WAL
# tidak-dijalankan
# bersihkan direktori pemulihan sebelumnya (jika ada)
rm -rf /tmp/pg_recovery

# base backup dengan stream WAL ke direktori lokal
pg_basebackup -D /tmp/pg_recovery -X fetch -c fast

# archive_command di postgresql.conf
# archive_command = 'aws s3 cp %p s3://bucket-wal/%f'

# di instance pemulihan, buat recovery.signal
# touch /tmp/pg_recovery/recovery.signal

# recovery_target_time di postgresql.auto.conf
# recovery_target_time = '2026-11-07 10:30:00+00'

Estimasi ukuran backup dan waktu restore#

Pilihan metode backup memengaruhi ruang penyimpanan dan waktu restore. Skrip Python berikut memodelkan telemetri detilan dengan 10 sensor pada tiga retensi berbeda, lalu menghitung ukuran raw, ukuran terkompresi, ukuran pg_dump, dan ukuran WAL harian. Skrip juga mengestimasi waktu restore berdasarkan asumsi kecepatan baca 50 MB per detik, sehingga perbedaan antara metode menjadi nyata. Skrip tidak menjalankan SQL atau pg_dump apa pun.

python estimasi_backup.py
"""Estimasi ukuran backup dan waktu restore pada TimescaleDB.

Skrip ini tidak menjalankan SQL atau pg_dump. Tujuannya memperlihatkan
bagaimana ukuran backup tumbuh seiring retensi data, dan bagaimana pilihan
metode backup (pg_dump logis vs base backup fisik vs PITR) mempengaruhi
ruang penyimpanan dan waktu restore. Skrip memodelkan telemetri detilan
dengan 10 sensor selama 30, 90, dan 180 hari, lalu menghitung ukuran
mentah, ukuran terkompresi, ukuran dump, dan ukuran WAL harian.
"""
from __future__ import annotations

import pandas as pd

SENSOR = 10
TITIK_PER_DETIK_PER_SENSOR = 1
BYTE_PER_BARIS_RAW = 46  # heap tuple kasar
RASIO_KOMPRESI = 10.0  # asumsi kompresi kolumnar 10x
RASIO_DUMP = 2.5  # pg_dump --format=custom kira-kira 2.5x lebih kecil dari raw
WAL_PER_HARI_GB = 0.1  # asumsi WAL harian untuk 10 sensor x detilan
KECEPATAN_RESTORE_MB_PER_DETIK = 50.0

RETENSI_HARI = [30, 90, 180]


def bangun_model(retensi_hari: list[int]) -> pd.DataFrame:
    baris = []
    for h in retensi_hari:
        titik_total = h * 86_400 * SENSOR * TITIK_PER_DETIK_PER_SENSOR
        raw_b = titik_total * BYTE_PER_BARIS_RAW
        compressed_b = raw_b / RASIO_KOMPRESI
        dump_b = raw_b / RASIO_DUMP
        wal_b = h * WAL_PER_HARI_GB * 1024 ** 3
        baris.append({
            "retensi_hari": h,
            "titik_total": titik_total,
            "raw_gb": raw_b / (1024 ** 3),
            "compressed_gb": compressed_b / (1024 ** 3),
            "dump_gb": dump_b / (1024 ** 3),
            "wal_gb": wal_b / (1024 ** 3),
        })
    return pd.DataFrame(baris)


def main() -> None:
    df = bangun_model(RETENSI_HARI)
    print("model telemetri: 1 titik/detik x 10 sensor, kompresi kolumnar 10x")
    print()

    print("estimasi ukuran backup per retensi (GB):")
    print(df.to_string(index=False))
    print()

    print("estimasi waktu restore (asumsi 50 MB/s sequensial):")
    for _, r in df.iterrows():
        for nama, gb in [("raw", r.raw_gb), ("compressed", r.compressed_gb),
                         ("dump", r.dump_gb), ("wal", r.wal_gb)]:
            mb = gb * 1024
            detik = mb / KECEPATAN_RESTORE_MB_PER_DETIK
            menit = detik / 60
            print(f"  retensi {int(r.retensi_hari):>3} hari, {nama:>10}: "
                  f"{gb:>7.2f} GB, restore ~{menit:>6.1f} menit")
    print()

    print("rasio ukuran (dump / raw):")
    for _, r in df.iterrows():
        print(f"  retensi {int(r.retensi_hari):>3} hari: "
              f"raw {r.raw_gb:>6.2f} GB -> dump {r.dump_gb:>5.2f} GB "
              f"({r.raw_gb / r.dump_gb:.1f}x lebih kecil)")
    print()
    print("padanan CLI Postgres (tidak dijalankan di sandbox):")
    print("  pg_dump --format=custom --compress=9 \\")
    print("    --table=suhu_sensor timescaledb_demo > backup.dump")
    print("  pg_basebackup -D /var/lib/postgresql/recovery \\")
    print("    -X stream -c fast")
    print("  restore: pg_restore -d timescaledb_demo backup.dump")


if __name__ == "__main__":
    main()
text Keluaran
model telemetri: 1 titik/detik x 10 sensor, kompresi kolumnar 10x

estimasi ukuran backup per retensi (GB):
 retensi_hari  titik_total   raw_gb  compressed_gb  dump_gb  wal_gb
           30     25920000 1.110435       0.111043 0.444174     3.0
           90     77760000 3.331304       0.333130 1.332521     9.0
          180    155520000 6.662607       0.666261 2.665043    18.0

estimasi waktu restore (asumsi 50 MB/s sequensial):
  retensi  30 hari,        raw:    1.11 GB, restore ~   0.4 menit
  retensi  30 hari, compressed:    0.11 GB, restore ~   0.0 menit
  retensi  30 hari,       dump:    0.44 GB, restore ~   0.2 menit
  retensi  30 hari,        wal:    3.00 GB, restore ~   1.0 menit
  retensi  90 hari,        raw:    3.33 GB, restore ~   1.1 menit
  retensi  90 hari, compressed:    0.33 GB, restore ~   0.1 menit
  retensi  90 hari,       dump:    1.33 GB, restore ~   0.5 menit
  retensi  90 hari,        wal:    9.00 GB, restore ~   3.1 menit
  retensi 180 hari,        raw:    6.66 GB, restore ~   2.3 menit
  retensi 180 hari, compressed:    0.67 GB, restore ~   0.2 menit
  retensi 180 hari,       dump:    2.67 GB, restore ~   0.9 menit
  retensi 180 hari,        wal:   18.00 GB, restore ~   6.1 menit

rasio ukuran (dump / raw):
  retensi  30 hari: raw   1.11 GB -> dump  0.44 GB (2.5x lebih kecil)
  retensi  90 hari: raw   3.33 GB -> dump  1.33 GB (2.5x lebih kecil)
  retensi 180 hari: raw   6.66 GB -> dump  2.67 GB (2.5x lebih kecil)

padanan CLI Postgres (tidak dijalankan di sandbox):
  pg_dump --format=custom --compress=9 \
    --table=suhu_sensor timescaledb_demo > backup.dump
  pg_basebackup -D /var/lib/postgresql/recovery \
    -X stream -c fast
  restore: pg_restore -d timescaledb_demo backup.dump

Keluaran di atas memperlihatkan dua hal. Pertama, ukuran raw tumbuh linier dengan retensi, yaitu 1,11 GB pada 30 hari menjadi 6,66 GB pada 180 hari, sedangkan ukuran dump selalu 2,5 kali lebih kecil berkat kompresi tingkat berkas pada pg_dump --format=custom. Kedua, ukuran WAL menjadi komponen yang paling besar pada retensi panjang, sebab arsip WAL harian terakumulasi tanpa dikompresi sekuat kompresi kolumnar hypertable. Pada retensi 180 hari, WAL mencapai 18 GB, jauh melebihi ukuran dump yang hanya 2,67 GB. Karena itu, pemilihan retensi arsip WAL menjadi keputusan yang menentukan ruang penyimpanan PITR, dan biasanya dipilih lebih pendek daripada retensi hypertable itu sendiri.

Postur backup 3-2-1#

Postur backup yang lazim digunakan pada basis data produksi adalah aturan 3-2-1, yaitu tiga salinan data, dua media berbeda, dan satu salinan di luar lokasi. Pada TimescaleDB, tiga salinan itu biasanya berupa base backup pada storage utama, arsip WAL pada object storage terpisah, dan dump logis pada object storage jarak jauh. Dua media berbeda dapat berupa SSD lokal untuk base backup dan object storage untuk arsip WAL, sedangkan satu salinan di luar lokasi mengarah ke object storage pada region yang berbeda. Postur ini menanggulangi kegagalan pada level media, level instance, dan level region sekaligus.

Kesalahan umum#

  • Mengandalkan satu jalur backup saja, misalnya hanya pg_dump. Bila dump rusak atau restore gagal karena perbedaan versi, tidak ada jalur alternatif. Postur backup sebaiknya minimal mencakup base backup dan dump logis.
  • Membiarkan arsip WAL tumbuh tanpa kebijakan retensi. Pada telemetri berat, WAL harian menjadi puluhan GB per hari, sehingga retensi arsip WAL sebaiknya lebih pendek daripada retensi hypertable.
  • Tidak menguji restore secara berkala. Backup yang belum pernah direstore adalah hipotesis, bukan jaminan. Uji restore sebaiknya dilakukan minimal sekali per kuartal pada instance terpisah.

Ringkasan#

  • Pemantauan TimescaleDB menggunakan tampilan timescaledb_information untuk metadata ekstensi dan metrik Postgres biasa untuk performa, sehingga keduanya saling melengkapi.
  • pg_dump menghasilkan backup logis yang portabel tetapi lambat saat restore, sedangkan pg_basebackup menghasilkan backup fisik yang cepat saat restore dan menjadi titik awal PITR.
  • Postur backup 3-2-1, yaitu tiga salinan, dua media, dan satu di luar lokasi, menjadi praktik standar yang menanggulangi kegagalan pada beberapa level sekaligus.

Referensi#