2 poin oleh GN⁺ 2026-02-24 | 1 komentar | Bagikan ke WhatsApp
  • Transaksi adalah struktur untuk menjalankan beberapa operasi di database sebagai satu unit atomik, mencakup baca, tulis, pembaruan, dan penghapusan
  • MySQL dan Postgres mengontrol transaksi dengan begin; dan commit;, lalu membatalkan perubahan dengan rollback; saat terjadi kegagalan atau error
  • Kedua database sama-sama menjamin consistent read, tetapi Postgres menggunakan MVCC (Multi-Version Concurrency Control), sedangkan MySQL menggunakan undo log
  • Isolation level mengontrol interferensi data antartransaksi, dan dibagi menjadi empat tingkat dari Serializable hingga Read Uncommitted
  • Postgres dan MySQL menangani konflik penulisan bersamaan dengan cara berbeda; Postgres memakai validasi optimistis, sementara MySQL menggunakan row-level locking

Konsep dasar transaksi

  • Transaksi adalah struktur yang mengelompokkan beberapa operasi SQL di database menjadi satu unit eksekusi atomik
    • Dimulai dengan begin; dan diakhiri dengan commit;, dengan beberapa kueri dapat dijalankan di antaranya
    • Pada saat commit;, semua perubahan diterapkan sekaligus
  • Saat terjadi gangguan tak terduga (mati listrik, error disk, dan sebagainya) atau pembatalan yang disengaja, perubahan dapat dikembalikan dengan rollback;
    • Postgres mendukung pemulihan dengan WAL (Write-Ahead Log)
  • Data yang diubah selama transaksi akan terisolasi dan tidak terlihat dari sesi lain
    • Saat rollback;, semua perubahan dibatalkan sehingga database kembali ke keadaan semula
Iklan

Consistent read

  • Transaksi harus mempertahankan tampilan data yang konsisten yang tidak terpengaruh oleh perubahan eksternal selama eksekusi
  • MySQL dan Postgres mendukung hal ini pada mode REPEATABLE READ ke atas, tetapi implementasinya berbeda
    • Postgres: mengelola versi setiap baris dengan MVCC (Multi-Version Concurrency Control)
    • MySQL: merekonstruksi versi lama dengan undo log

Penyimpanan multi-versi baris di Postgres

  • Setiap kali baris diperbarui, versi baru dibuat; versi lama mencatat ID transaksi di xmax, dan versi baru di xmin
  • Sebelum transaksi di-commit, sesi lain tidak dapat melihat perubahan tersebut
  • Setelah commit, versi baru diterapkan ke seluruh database
  • Saat rollback;, perubahan dibuang dan data asli tetap dipertahankan
  • Versi baris lama dibersihkan dengan perintah VACUUM FULL untuk merebut kembali ruang penyimpanan

Undo log di MySQL

  • MySQL menimpa baris secara langsung, tetapi mencatat nilai sebelumnya di undo log sehingga dapat dipulihkan bila diperlukan
  • Setiap baris memiliki metadata xid (ID transaksi modifikasi terbaru) dan ptr (pointer undo log)
  • Saat beberapa transaksi berjalan bersamaan, setiap transaksi secara selektif mengambil versi yang dibutuhkan melalui undo log
  • Beberapa catatan undo log dapat ada untuk baris yang sama, dan versi yang sesuai dipilih berdasarkan ID transaksi

Isolation level

  • Ini adalah pengaturan untuk mengontrol interferensi data antartransaksi, dengan tingkat pelonggaran berurutan Serializable → Repeatable Read → Read Committed → Read Uncommitted
  • Serializable: semua transaksi berjalan seolah-olah dieksekusi secara berurutan
  • Repeatable Read: hasil tetap sama saat kueri yang sama dijalankan ulang, tetapi phantom read masih mungkin terjadi
  • Read Committed: dapat membaca perubahan dari transaksi lain yang sudah di-commit
  • Read Uncommitted: mengizinkan dirty read, tingkat perlindungan paling rendah tetapi performanya tinggi
Iklan

Penulisan bersamaan

  • Cara menangani dua transaksi yang memodifikasi baris yang sama secara bersamaan berbeda-beda tergantung database

MySQL: Row-level locking

  • Shared lock (S lock) memungkinkan beberapa transaksi membaca secara bersamaan
  • Exclusive lock (X lock) hanya memungkinkan satu transaksi memodifikasi baris
  • Dalam mode SERIALIZABLE, setiap pembaruan harus memperoleh X lock, dan deadlock dapat terjadi saat ada konflik
  • MySQL mendeteksi deadlock dan menghentikan salah satu transaksi

Postgres: Serializable Snapshot Isolation

  • Postgres menggunakan predicate lock untuk melacak akses pada tingkat himpunan baris
    • Contoh: lock untuk kondisi WHERE id BETWEEN 10 AND 20
  • Akses nyata tidak langsung diblokir; sistem mendeteksi konflik dan menghentikan transaksi bila terjadi pelanggaran
  • Dengan optimistic conflict resolution, deadlock dapat dihindari
  • Sama seperti MySQL, saat konflik terjadi satu transaksi akan dihentikan dan aplikasi perlu menerapkan logika retry

Kesimpulan

  • Transaksi adalah komponen inti database yang menjamin ACID (Atomicity, Consistency, Isolation, Durability)
  • Postgres dan MySQL mencapai tujuan yang sama dengan struktur internal yang berbeda
  • Memahami empat isolation level dan cara kerja transaksi membantu pengoperasian database yang lebih stabil

1 komentar

 
GN⁺ 2026-02-24
Komentar Hacker News
  • Tulisan ini terasa agak kurang memadai.
    Menurut saya, akan lebih intuitif bila penjelasan level isolasi dimulai dari konsep serializability, alih-alih berpusat pada phenomena yang didefinisikan dalam standar SQL.
    Serializability bisa dilihat sebagai generalisasi dari thread safety, dan jika ini hilang, akan muncul bug yang hasilnya berubah tergantung urutan eksekusi.
    Berbagai level isolasi di database pada dasarnya hanyalah bentuk pelonggaran dari jaminan ini, sehingga pengguna harus memastikan jaminan tersebut dengan cara lain.
    Phenomena hanyalah alat untuk memvisualisasikan situasi non-serial, bukan sesuatu yang terhubung langsung dengan serializability.
    Misalnya, cluster Kubernetes pun bisa beroperasi secara serializable jika menggunakan controller yang dirancang dengan baik.

    • Saya penulisnya. Terima kasih atas masukan yang bagus.
      Membahas transaksi, level isolasi, dan MVCC sekaligus, bahkan sampai membandingkan beberapa DB, adalah pekerjaan yang sangat besar.
      Saya berusaha menyeimbangkan kedalaman teknis, aksesibilitas, dan panjang tulisan.
    • Membagikan tautan Jepsen: analisis MariaDB Galera Cluster.
      Menurutnya akan lebih baik jika ada lebih banyak notasi dan kutipan.
    • Sebagian besar RDBMS menyediakan isolasi serializable bila diperlukan.
      Namun jika dipakai tanpa perlu, biaya koordinasi antar transaksi meningkat sehingga konkurensi dan throughput menurun.
    • Tanggapannya: kalau begitu, coba usulkan penjelasan yang lebih baik.
  • Transaksi juga bisa dibayangkan seperti snapshot pada filesystem copy-on-write (btrfs, zfs), tetapi menurut saya analogi branch Git lebih intuitif.
    BEGIN adalah membuat branch, UPDATE adalah commit, ROLLBACK adalah menghapus branch, dan COMMIT sama seperti git merge.
    Jika terjadi konflik, DB akan mencoba melakukan merge per baris, dan jika gagal, akan rollback atau memaksa merge tergantung konfigurasi.
    READ UNCOMMITTED mengutamakan merge cepat, sedangkan SERIALIZABLE mengutamakan akurasi.
    Analogi seperti ini bisa membantu seseorang mendapat momen “aha!” dalam memahami konsep transaksi.

    • (Komentar singkat) Tanggapan yang mengisyaratkan concurrency.
  • Hal yang membuat banyak orang terkejut adalah Postgres dan MySQL secara default bukan mode serializable, melainkan read committed.
    Perbedaan performanya bukan sekadar “sedikit”, tetapi jauh lebih besar dalam praktiknya.
    Jika memakai read committed, kita perlu memperhatikan pengelolaan lock, dan constraint UNIQUE juga diperlukan untuk mencegah race condition.
    Meski begitu, cara ini tetap lebih disukai daripada harus menanggung penurunan performa dan masalah retry pada mode serializable.
    Referensi: dokumentasi resmi PostgreSQL

    • MySQL dan MariaDB(InnoDB) terbaru default-nya adalah repeatable read.
      Lihat dokumentasi MySQL dan dokumentasi MariaDB.
      MyISAM sekarang hampir tidak dipakai.
    • Masalah SERIALIZABLE bukan hanya performa, tetapi juga transaksi bisa gagal karena konflik, deadlock, atau timeout.
      Aplikasi harus bisa mendeteksinya dan memiliki strategi retry.
    • Oracle dan SQL Server juga default-nya read committed.
      Mode serializable terlihat keren di buku teks, tetapi dalam praktik hampir tidak dipakai.
  • Banyak tool database belakangan ini lebih memprioritaskan berbagi pembaruan real-time daripada ACID.
    Misalnya, di Airtable perubahan field langsung muncul di layar rekan kerja, tetapi karena tidak ada transaksi, ada risiko inkonsistensi data.
    Terkait hal ini, lihat tulisan blog VisualDB.

    • Tanggapan yang mengatakan ini terlihat seperti promosi produk yang menyamar sebagai kritik terhadap pesaing.
  • Membaca blog PlanetScale benar-benar menyenangkan.
    Penasaran tool apa yang dipakai untuk visualisasinya.

    • Saya penulisnya. Terima kasih!
      Visualisasinya dibuat dengan js + gsap(https://gsap.com).
  • Jika tertarik pada topik ini, saya sangat merekomendasikan 『Designing Data-Intensive Applications』.
    Buku itu membahas bukan hanya berbagai level isolasi, tetapi juga ambigu definisi ACID.
    Katanya edisi kedua akan segera terbit.

  • Transaksi pada sistem MVCC seperti Postgres mirip dengan snapshot pada filesystem copy-on-write.
    Saat BEGIN, snapshot data dibuat, dan UPDATE hanya diterapkan pada salinan privat.
    Saat ROLLBACK, salinan itu dibuang, dan saat COMMIT, snapshot baru menjadi versi resmi.
    Analogi ini bisa menjadi titik yang membuat seseorang benar-benar memahami konsep transaksi dengan jelas.
    P.S. Analogi branch Git juga memungkinkan.

    • Tidak sepenuhnya akurat. DB sebenarnya menggunakan branching dan locking sekaligus.
      Dalam kasus seperti SELECT lalu UPDATE, satu thread bisa saja terblokir.
      Hari ini saya berencana bereksperimen di MySQL untuk melihat apakah ini bisa diubah menjadi satu query saja.
  • Dulu transaksi sering ditanyakan saat wawancara backend.
    Semua orang pernah memakainya, tetapi tingkat pemahamannya berbeda-beda tergantung pengalaman.
    Walau tidak hafal semua level isolasi, hanya dengan tahu bahwa masing-masing berperilaku berbeda saja sudah bisa menunjukkan rasa ingin tahu dan pemahaman sistem.

    • Walaupun nama level isolasinya sama, perilakunya bisa berbeda antar DB, jadi detail perilaku per kasus harus diperiksa.
  • Penjelasan tentang “phantom read” bisa menimbulkan salah paham.
    Pada repeatable read, nilai baris yang sudah ada tidak berubah, tetapi baris baru bisa ditambahkan.
    Karena baris yang ada tidak berubah atau dihapus, poin itu perlu dijelaskan dengan tegas.

  • Kalimat “tidak ada hubungannya dengan xmin/xmax” terasa tidak lengkap.
    Visualisasi yang menunjuk ke header tabel saat commit juga terasa aneh.
    Bukankah sebenarnya xmax/xmin adalah mekanisme inti untuk menentukan apakah suatu commit sudah berlaku?
    Jika subtransaksi juga dipertimbangkan, jadinya lebih rumit.
    Meski begitu, visualisasi dan penjelasannya secara keseluruhan tetap menyenangkan untuk dibaca.

    • Saya juga merasa sayang karena konsep xmax/xmin tidak dimasukkan.
      Itu penting untuk memahami level isolasi, sampai terasa seperti ada satu bagian yang hilang.