👨‍💻
Sammi
  • Hello
  • About Me
    • Links
    • My Daily Uses
  • PostgreSQL → Partitioning
  • Belajar System Programming Menggunakan Go
    • Mengingat Kembali Tentang Concurrency dan Parallelism
  • Memory Management
  • Explore
    • Testing 1: Load and performance testing
    • Data Structure 1: Bloom Filter
    • System Design 1: Back of The Envelope Estimation
    • System Design 2: A Framework For System Design Interviews
    • System Design 3: Design a URL Shortener
    • Belajar RabbitMQ
  • Belajar Kubernetes
  • Notes
    • Permasalahan Penggunaan JWT dan Solusinya dengan PASETO
    • First Principle Thinking
    • The Over-Engineering Pendulum
    • Data-Oriented Programming
  • CAP Theorem
  • Go Series: Safer Enum
  • Go Series: Different types of for loops in Golang?
  • Go Series: Mutex & RWMutex
  • Setup VM Production Ready Best Practice
  • BEHAVIOUR QUESTION
  • Invert, always invert
  • Mengapa Tidak Menggunakan Auto-Increment ID?
  • I Prefix dan Impl Suffix
  • ACID
  • MVCC Di Postgres
  • Implicit Interface di Go
  • Transaction di Postgres
  • Kriteria Kolom yang Cocok Dijadikan Index
  • Misc
    • Go Project
    • Talks
    • Medium Articles
  • PostgreSQL
    • Introduction
  • English
    • Vocab
Powered by GitBook
On this page
  • 🔹 1. Apa Itu MVCC?
  • 🔹 2. Konsep Dasar MVCC
  • 🔹 3. Algoritma Visibilitas Tuple
  • 🔹 4. Snapshot Isolation vs Isolation Level
  • 🔹 5. Transaction ID Wraparound
  • 🔹 6. HOT (Heap Only Tuple) Updates
  • 🔹 7. Write Conflict dan Locking
  • 🔹 8. VACUUM dan Autovacuum
  • 🔹 9. Impact of Long-Running Transactions
  • 🔹 10. PostgreSQL vs Sistem Lain
  • 🔹 11. Diagram Alur MVCC
  • 🔹 12. Kesimpulan dan Best Practices

MVCC Di Postgres

🔹 1. Apa Itu MVCC?

MVCC adalah teknik yang memungkinkan PostgreSQL mengizinkan concurrent access dengan menyimpan beberapa versi data. Setiap transaksi melihat snapshot data yang konsisten sesuai waktu mulai transaksi.

Tujuan Utama:

  • Isolasi Transaksi: Transaksi tidak saling melihat perubahan yang belum di-commit.

  • Non-Blocking Reads: Operasi baca tidak memblokir operasi tulis, dan sebaliknya.

  • Konsistensi: Setiap transaksi bekerja dengan data yang stabil selama eksekusi.


🔹 2. Konsep Dasar MVCC

Metadata pada Tuple:

  • xmin: Transaction ID (XID) yang membuat tuple (INSERT/UPDATE).

  • xmax: XID yang menghapus/mengunci tuple (DELETE/UPDATE).

  • ctid: Identifier fisik lokasi tuple di heap.

  • cmin/cmax: Command ID dalam transaksi (untuk operasi dalam transaksi yang sama).

Snapshot:

  • Definisi: Snapshot adalah representasi keadaan database pada suatu waktu tertentu.

  • Komponen:

    • Daftar XID transaksi yang sedang aktif (in-progress) saat snapshot diambil.

    • XID tertinggi yang dianggap sudah commit (latest completed XID).

  • Pembuatan:

    • Read Committed: Snapshot baru diambil setiap pernyataan SQL.

    • Repeatable Read/Serializable: Snapshot diambil saat transaksi dimulai.


🔹 3. Algoritma Visibilitas Tuple

PostgreSQL menggunakan kombinasi XID, snapshot, dan CLOG (Commit Log) untuk menentukan visibilitas tuple.

Langkah Pengecekan:

  1. Cek xmin:

    • Jika xmin belum commit (berada dalam daftar in-progress XID), tuple tidak terlihat.

    • Jika xmin sudah commit dan lebih kecil dari XID transaksi, lanjut ke xmax.

  2. Cek xmax:

    • Jika xmax tidak ada (0) atau belum commit, tuple terlihat.

    • Jika xmax sudah commit dan lebih kecil dari XID transaksi, tuple tidak terlihat (sudah dihapus).

Contoh:

-- Transaksi A (XID=100)
BEGIN;
UPDATE users SET name = 'Alice' WHERE id = 1; -- xmin=100, xmax=0 (baru)

-- Transaksi B (XID=101)
BEGIN;
SELECT * FROM users WHERE id = 1; -- Masih melihat versi lama (xmax=100)

🔹 4. Snapshot Isolation vs Isolation Level

Isolation Level dan MVCC:

Level Isolasi
Mekanisme MVCC

Read Committed

Snapshot baru setiap query. Lihat perubahan yang sudah di-commit.

Repeatable Read

Snapshot diambil saat transaksi dimulai. Data tidak berubah selama transaksi.

Serializable

Menggunakan predikat lock untuk mencegah serialization anomalies.

Repeatable Read Example:

-- Transaksi A
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM users; -- Snapshot diambil di sini.

-- Transaksi B
UPDATE users SET name = 'Bob' WHERE id = 1;
COMMIT;

-- Transaksi A (masih melihat data sebelum B commit)
SELECT * FROM users;

🔹 5. Transaction ID Wraparound

Masalah:

  • XID di PostgreSQL adalah 32-bit (hingga ~4 miliar transaksi).

  • Jika XID mencapai batas, akan terjadi wraparound (XID 0 dianggap lebih baru dari XID 4 miliar).

Solusi: Freezing:

  • Tuple dengan XID sangat lama ditandai sebagai frozen (dianggap selalu valid).

  • Proses VACUUM FREEZE akan mengubah xmin menjadi FrozenTransactionId untuk mencegah wraparound.

Monitoring:

  • Cek pg_database.datfrozenxid untuk melihat XID tertua yang belum dibekukan.

  • Jika age(datfrozenxid) > 2 miliar, muncul warning transaction ID wraparound.


🔹 6. HOT (Heap Only Tuple) Updates

Optimisasi untuk Mengurangi Bloat:

  • Jika UPDATE tidak mengubah kolom yang di-index, tuple baru ditempatkan di halaman heap yang sama.

  • Manfaat:

    • Tidak perlu update index (ctid lama mengarah ke tuple baru).

    • Mengurangi fragmentasi dan bloat.

  • Syarat:

    • Tidak ada perubahan kolom yang di-index.

    • Ada ruang kosong di halaman heap.


🔹 7. Write Conflict dan Locking

Konflik UPDATE:

  • Dua transaksi mencoba UPDATE baris yang sama: transaksi kedua akan menunggu (atau gagal jika menggunakan NOWAIT).

  • PostgreSQL menggunakan row-level locks (FOR UPDATE) untuk menangani ini.

Contoh Deadlock:

-- Transaksi A
UPDATE users SET name = 'A' WHERE id = 1;
UPDATE users SET name = 'B' WHERE id = 2; -- Menunggu Transaksi B

-- Transaksi B
UPDATE users SET name = 'B' WHERE id = 2;
UPDATE users SET name = 'A' WHERE id = 1; -- Deadlock!

🔹 8. VACUUM dan Autovacuum

Tugas VACUUM:

  • Menghapus dead tuples (versi data yang tidak terlihat oleh transaksi manapun).

  • Membekukan XID lama (freeze).

  • Update statistik untuk query planner.

Autovacuum Tuning:

-- Contoh konfigurasi di postgresql.conf:
autovacuum_vacuum_scale_factor = 0.2 -- Jalankan VACUUM jika 20% baris mati.
autovacuum_vacuum_cost_limit = 2000 -- Batas beban autovacuum.

🔹 9. Impact of Long-Running Transactions

Transaksi yang lama terbuka akan:

  • Mencegah VACUUM menghapus dead tuples yang dibuat sebelum transaksi dimulai.

  • Menyebabkan table bloat dan penurunan performa.

  • Solusi: Monitor menggunakan query:

    SELECT pid, query, xact_start FROM pg_stat_activity 
    WHERE state = 'idle in transaction' OR xact_start < NOW() - INTERVAL '1 hour';

🔹 10. PostgreSQL vs Sistem Lain

Perbandingan MVCC:

Sistem
Implementasi MVCC
Kelebihan

PostgreSQL

Heap-based, menyimpan semua versi di tabel

Fleksibel, mudah di-tune.

MySQL InnoDB

Menggunakan undo logs di tablespace

Bloat lebih terkontrol.

Oracle

Undo segments + Redo logs

Optimized untuk high concurrency.


🔹 11. Diagram Alur MVCC

Berikut ilustrasi alur operasi UPDATE dengan MVCC:

1. Baris Lama: (xmin=100, xmax=0)
2. Transaksi XID=200 melakukan UPDATE:
   - Tandai baris lama dengan xmax=200.
   - Tambahkan baris baru dengan xmin=200.
3. Transaksi XID=300 membaca:
   - Lihat baris lama (xmax=200 belum commit) atau baru (xmin=200) tergantung snapshot.

🔹 12. Kesimpulan dan Best Practices

Best Practices:

  • Hindari transaksi panjang yang memblokir VACUUM.

  • Monitor autovacuum dan sesuaikan parameter sesuai beban.

  • Gunakan REPEATABLE READ jika membutuhkan snapshot stabil.

  • Optimalkan UPDATE dengan HOT (hindari mengubah kolom terindeks).

Peringatan Umum:

  • Bloat: Selalu pantau n_dead_tups di pg_stat_all_tables.

  • Wraparound: Pastikan autovacuum berjalan lancar.

  • Lock Contention: Gunakan pg_lock untuk lacak konflik.


Dengan memahami MVCC secara mendalam, Anda bisa mengoptimalkan performa PostgreSQL dan menghindari masalah umum seperti bloat, lock contention, dan transaction wraparound.

PreviousACIDNextImplicit Interface di Go

Last updated 13 days ago