Lompat ke konten
17 menit bacamateri 25 dari 96

Nyatakan invarians bisnis

Bedain atomicity transaksi, durabilitas, dan kebenaran aplikasi. Transaksi nggak otomatis bikin bisnis kamu bener.

Ditinjau 26 Oktober 2026

Pertanyaan

Aturan apa yang nggak boleh pernah rusak, dan jaminan mana yang beneran nahan aturan itu?

Setelah baca ini, kamu bisa nulis invarians bisnis sebuah fitur sebagai kalimat yang bisa dicek, terus misahin bagian yang dijaga database (atomicity, durabilitas, constraint) dari bagian yang tetap jadi tanggung jawab kode aplikasi.

Prasyarat dan contoh

Kamu sudah paham model data dan indeks dari M03 dan M04, dan tahu apa itu tabel, baris, dan constraint.

Toko tiket punya konser dengan 100 kursi. Aturannya: jumlah tiket terjual tidak pernah melebihi 100. Itu invarians: kondisi yang harus benar sebelum dan sesudah setiap operasi, di semua urutan eksekusi yang mungkin.

Kode pembelian yang kelihatan wajar:

BEGIN;
  SELECT sisa FROM stok WHERE konser = 7;      -- sisa = 1
  -- aplikasi: if sisa > 0
  UPDATE stok SET sisa = sisa - 1 WHERE konser = 7;
  INSERT INTO tiket (konser, pembeli) VALUES (7, :pembeli);
COMMIT;

Transaksi ini atomik dan tahan crash. Tapi dua pembeli yang jalan bersamaan sama-sama baca sisa = 1, sama-sama lolos if, dan dua tiket terbit buat satu kursi. Setiap transaksi benar sendirian. Invarians-nya tetap rusak.

Mekanisme

Atomicity. Semua perubahan dalam satu transaksi terjadi, atau nggak ada yang terjadi. Kalau INSERT tiket gagal, UPDATE stok ikut dibatalkan. Ini soal kegagalan di tengah jalan, bukan soal pembeli lain.

Durabilitas. Setelah COMMIT dikonfirmasi, hasilnya bertahan walau proses atau mesin mati. Biasanya lewat write-ahead log yang di-flush ke disk. Jaminan ini punya syarat: konfigurasi (misalnya synchronous_commit di PostgreSQL) dan perangkat disk yang jujur soal flush. Detailnya ada di M09.

Isolation. Seberapa jauh transaksi yang jalan bersamaan saling kelihatan. Ini yang nentuin apakah dua pembeli di atas bisa saling nggak tahu. Isolation punya tingkat, dan kebanyakan engine default-nya bukan yang paling ketat (lihat M05.02).

Constraint basis data. Tempat paling murah buat nahan invarians. Contoh:

ALTER TABLE stok ADD CONSTRAINT sisa_nonnegatif CHECK (sisa >= 0);

Dengan constraint ini, UPDATE kedua yang bikin sisa = -1 ditolak database, siapa pun yang nulis dan seramai apa pun trafiknya. Constraint cuma bisa mengekspresikan aturan yang bisa dicek dari baris itu sendiri atau lewat UNIQUE, FOREIGN KEY, dan sejenisnya.

Kebenaran aplikasi. Aturan seperti "satu pengguna maksimal 4 tiket per konser" atau "saldo semua akun harus nol saat dijumlah" nggak selalu bisa jadi constraint satu baris. Aturan itu perlu dijaga lewat kunci, pembaruan atomik, atau desain data yang bikin pelanggarannya mustahil (M05.03).

Daftar yang berguna. Buat tiap fitur tulis tiga kolom: invarians, penjaganya, dan apa yang terjadi kalau penjaganya gagal. Contoh singkat:

| Invarians | Penjaga | Kalau gagal | | --- | --- | --- | | sisa >= 0 | CHECK di tabel | Transaksi ditolak, pembeli dapat "habis" | | Satu tiket per kursi | UNIQUE (konser, kursi) | Insert kedua ditolak | | Maks 4 tiket per pengguna | Kode + kunci per pengguna | Pengguna bisa beli 5 |

Saat rancangan ini gagal

  • Menyamakan "pakai transaksi" dengan "aman". Transaksi memberi atomicity, bukan jaminan bahwa keputusan yang diambil dari data yang dibaca masih valid saat commit.
  • Cek di aplikasi, tulis di database. Pola baca, if, tulis, punya jendela waktu di tengah. Pada 200 permintaan/detik untuk kursi terakhir, jendela beberapa milidetik sudah cukup buat oversell.
  • Invarians hanya di komentar atau dokumentasi. Kode baru, skrip admin, atau import data nggak membaca komentar. Constraint tetap berlaku untuk semuanya.
  • Mengira durabilitas berarti kebenaran. Data yang salah pun disimpan dengan tahan crash. Durabilitas melestarikan hasilnya, benar atau salah.
  • Invarians lintas sistem. Kalau stok di database dan tiket di layanan lain, satu transaksi nggak mencakup keduanya (M05.06).

Latihan

Sebuah dompet digital punya aturan: saldo pengguna tidak boleh negatif, dan transfer memindahkan uang dari A ke B tanpa menambah atau mengurangi total. Kode transfer: baca saldo A, cek saldo >= jumlah, kurangi A, tambah B, semuanya dalam satu transaksi dengan isolation default.

Tulis invarians sebagai kalimat, tentukan penjaga untuk masing-masing, dan sebut satu celah yang masih ada.

Lihat pembahasan

Invarians:

  1. Untuk setiap akun, saldo >= 0.
  2. Untuk setiap transfer, jumlah yang keluar dari A sama dengan yang masuk ke B, jadi total saldo tidak berubah.

Penjaga:

  • Aturan 1: CHECK (saldo >= 0) di tabel akun. Ini menolak pembaruan yang bikin saldo negatif walau dua transfer dari akun yang sama jalan bersamaan.
  • Aturan 2: atomicity. Pengurangan A dan penambahan B ada di satu transaksi, jadi nggak ada keadaan di mana uang hilang di tengah. Jangan menaruhnya di dua transaksi atau dua layanan.

Celah: kode yang membaca saldo lalu mengecek di aplikasi masih bisa salah jika dua transfer membaca saldo yang sama. Dengan CHECK, salah satunya ditolak (bagus, tapi aplikasi harus menangani error itu sebagai "saldo kurang", bukan 500). Tanpa CHECK, dua transfer Rp80.000 dari saldo Rp100.000 bisa lolos dan saldo jadi -Rp60.000.

Jawaban yang bagus memisahkan aturan yang bisa jadi constraint dari aturan yang butuh kunci atau pembaruan atomik, dan nggak mengandalkan "sudah pakai transaksi".

Terkait

  • M05.02 Amati anomali isolasi menjelaskan kenapa dua transaksi yang benar bisa melanggar invarians bersama.
  • M05.03 Koordinasikan perubahan konkuren membahas alat untuk menjaga aturan yang nggak bisa jadi constraint.
  • M03 (model data) dan M04 (indeks, termasuk indeks unik) menyediakan constraint yang dipakai di sini.
  • M09 membahas durabilitas dan WAL lebih dalam.

Catatan

  • Asumsi: satu database relasional dengan transaksi ACID dan constraint standar.
  • Yang nggak dibahas: detail implementasi WAL, dan transaksi terdistribusi seperti two-phase commit.
  • Istilah ACID di sini dipakai praktis. Makna "C" (consistency) di ACID sebenarnya adalah invarians yang kamu definisikan sendiri, bukan sesuatu yang diberikan database.
  • Terakhir ditinjau: 26 Oktober 2026.

Isi · System Design