Daftar isi
Ini artikel contoh untuk pembelajaran. Tanggal publikasi dan catatan transaksi bersifat ilustratif.
Timeout tidak memberi tahu apakah penulisan sudah commit. Mengulang append karena itu dapat menggandakan data. Operasi idempoten menghasilkan keadaan tujuan yang sama ketika input identik diterapkan lagi. Contoh PostgreSQL 18 ini menunjukkan sifat tersebut secara konkret.
Tetapkan identitas dan revisi
Sumber memasok satu amount terkini per transaksi dan source_revision yang meningkat. Revisi lebih besar menggantikan revisi kecil. Revisi sama wajib memiliki payload sama; payload bertentangan pada revisi sama adalah kesalahan sumber untuk dikarantina. Amount memakai satu mata uang.
CREATE TABLE transaction_state (
transaction_id text PRIMARY KEY,
source_revision bigint NOT NULL,
amount numeric(12, 2) NOT NULL
);
INSERT INTO transaction_state AS current_state
(transaction_id, source_revision, amount)
VALUES ('T-10', 2, 130.00)
ON CONFLICT (transaction_id) DO UPDATE
SET source_revision = EXCLUDED.source_revision,
amount = EXCLUDED.amount
WHERE EXCLUDED.source_revision > current_state.source_revision;
Primary key menetapkan identitas. ON CONFLICT memakai kunci itu untuk memilih pembaruan alih-alih insert ganda. Kondisi WHERE mencegah revisi lama menggantikan nilai baru. Pengulangan revisi 2 mempertahankan baris tanpa perubahan. Kondisi ini juga mengabaikan konflik pada revisi sama, sehingga validasi kontrak itu harus dilakukan sebelum penulisan.
Uji kegagalan pada batas proses
| Input setelah revisi 2 | Tujuan yang diharapkan |
|---|---|
| Revisi 2 sama, amount 130.00 | Satu baris, amount 130.00 |
| Revisi 1 lama, amount 125.00 | Satu baris, amount 130.00 |
| Revisi 3 baru, amount 135.00 | Satu baris, amount 135.00 |
| Revisi 2 dengan payload bertentangan | Karantina sebelum ditulis |
Kirim setiap skenario dua kali. Bandingkan seluruh baris dan jumlah baris. Jika batch memiliki beberapa versi satu kunci, pilih revisi terbaru secara deterministik sebelum satu pernyataan upsert. PostgreSQL tidak mengizinkan satu pernyataan memperbarui baris tujuan yang sama dua kali melalui ON CONFLICT.
Pisahkan keadaan dan efek samping
Upsert database aman tidak membuat email atau panggilan API eksternal otomatis idempoten. Gunakan kunci idempotensi yang didukung tujuan atau transactional outbox dengan penerima yang melakukan deduplikasi. Catat input batch dan checkpoint selesai secara tahan gagal. Majukan checkpoint hanya setelah efek yang dimaksud aman.
Tambahkan percobaan ulang dengan jeda terbatas untuk kegagalan sementara, arahkan catatan invalid untuk penyelidikan, dan cocokkan hitungan input diterima serta ditolak. Uji kegagalan tepat setelah commit sebelum acknowledgement. Jika pemulihan menggandakan efek atau kehilangan koreksi, kontrak percobaan ulang belum lengkap.