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:
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 kexmax
.
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:
🔹 4. Snapshot Isolation vs Isolation Level
Isolation Level dan 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:
🔹 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
menjadiFrozenTransactionId
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:
🔹 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:
🔹 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:
🔹 10. PostgreSQL vs Sistem Lain
Perbandingan MVCC:
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:
🔹 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
dipg_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.
Last updated