BEGIN, COMMIT, dan ROLLBACK

Mengelompokkan beberapa perubahan menjadi satu unit kerja yang utuh.

Daftar isi

Topik ini membahas disiplin menulis transaksi secara manual, yaitu BEGIN untuk membuka unit kerja, COMMIT untuk menetapkannya, dan ROLLBACK untuk membatalkannya. Tanpa ketiganya, setiap pernyataan berdiri sebagai transaksi sendirian, dan kegagalan di tengah rangkaian menyisakan keadaan setengah jadi.

Blok penyiapan dataset#

bash
# siapkan ulang tabel dan data contoh untuk topik ini
PGOPTIONS='-c client_min_messages=warning' psql -q -U postgres -d perpustakaan <<'SQL'
DROP TABLE IF EXISTS peminjaman, buku, anggota, kategori CASCADE;
CREATE TABLE kategori (id SERIAL PRIMARY KEY, nama TEXT NOT NULL UNIQUE);
CREATE TABLE anggota (id SERIAL PRIMARY KEY, nama TEXT NOT NULL, email TEXT UNIQUE, bergabung DATE NOT NULL, aktif BOOLEAN NOT NULL DEFAULT TRUE);
CREATE TABLE buku (id SERIAL PRIMARY KEY, judul TEXT NOT NULL, penulis TEXT NOT NULL, tahun INTEGER NOT NULL, kategori_id INTEGER REFERENCES kategori(id));
CREATE TABLE peminjaman (id SERIAL PRIMARY KEY, anggota_id INTEGER NOT NULL REFERENCES anggota(id), buku_id INTEGER NOT NULL REFERENCES buku(id), tanggal_pinjam DATE NOT NULL, tanggal_kembali DATE);
INSERT INTO kategori (nama) VALUES ('Pemrograman'), ('Sains'), ('Sejarah'), ('Fiksi'), ('Statistika');
INSERT INTO anggota (nama, email, bergabung, aktif) VALUES ('Ali Rahman', '[email protected]', '2024-01-15', TRUE), ('Budi Santoso', '[email protected]', '2024-03-02', TRUE), ('Citra Kirana', '[email protected]', '2024-05-20', FALSE), ('Dewi Lestari', '[email protected]', '2024-08-11', TRUE), ('Eka Pratama', NULL, '2025-01-30', TRUE);
INSERT INTO buku (judul, penulis, tahun, kategori_id) VALUES ('Dasar Basis Data', 'Sari Wulandari', 2021, 1), ('Jaringan Komputer', 'Ahmad Fauzi', 2019, 1), ('Fisika untuk Pemula', 'Rina Marlina', 2020, 2), ('Kimia Organik', 'Rina Marlina', 2022, 2), ('Sejarah Nusantara', 'Bambang Wijaya', 2018, 3), ('Cerita Kota Lama', 'Nur Aisyah', 2023, 4), ('Statistika Terapan', 'Sari Wulandari', 2022, 5), ('Algoritma dan Struktur Data', 'Ahmad Fauzi', 2021, 1);
INSERT INTO peminjaman (anggota_id, buku_id, tanggal_pinjam, tanggal_kembali) VALUES (1, 1, '2025-03-01', '2025-03-15'), (1, 7, '2025-03-05', '2025-03-20'), (2, 3, '2025-03-10', NULL), (3, 5, '2025-02-20', '2025-03-01'), (2, 1, '2025-04-02', NULL), (4, 6, '2025-04-07', NULL), (5, 8, '2025-04-09', '2025-04-25'), (4, 2, '2025-05-01', NULL);
SQL

Unit kerja yang dibuka dan ditetapkan#

Tanpa BEGIN, psql menjalankan setiap pernyataan dalam autocommit, artinya satu pernyataan satu transaksi. BEGIN menghentikan perilaku itu sampai COMMIT menetapkan seluruhnya atau ROLLBACK membatalkannya. Blok berikut mengubah keanggotaan di dalam transaksi, memeriksa hasilnya, lalu menetapkannya.

bash
# transaksi yang dibuka, diperiksa, lalu ditetapkan
psql -U postgres -d perpustakaan <<'SQL'
BEGIN;
UPDATE anggota SET aktif = FALSE WHERE id = 2 RETURNING nama, aktif;
SELECT aktif FROM anggota WHERE id = 2;
COMMIT;
SQL
text Keluaran
BEGIN
     nama     | aktif
--------------+-------
 Budi Santoso | f
(1 row)

UPDATE 1
 aktif
-------
 f
(1 row)

COMMIT

SELECT di dalam transaksi yang sama melihat perubahan yang belum ditetapkan, sifat yang normal bagi penulisnya sendiri, sedangkan sesi lain tetap melihat keadaan lama sampai COMMIT selesai. Setelah keluaran menunjukkan hasil yang diharapkan, COMMIT menetapkannya, dan urutan periksa-lalu-tetapkan inilah disiplin dasarnya.

ROLLBACK sebagai jalan keluar#

ROLLBACK membatalkan seluruh perubahan sejak BEGIN, dan manfaat terbesarnya pada skrip yang hasilnya tidak sesuai harapan. Blok berikut menjalankan perubahan yang kemudian disadari salah targetnya, lalu dibatalkan secara utuh.

bash
# perubahan yang disadari salah lalu dibatalkan
psql -U postgres -d perpustakaan <<'SQL'
BEGIN;
UPDATE anggota SET email = '[email protected]' WHERE id = 2;
SELECT nama, email FROM anggota WHERE id = 2;
ROLLBACK;
SELECT nama, email FROM anggota WHERE id = 2;
SQL
text Keluaran
BEGIN
UPDATE 1
     nama     |            email
--------------+------------------------------
 Budi Santoso | [email protected]
(1 row)

ROLLBACK
     nama     |      email
--------------+------------------
 Budi Santoso | [email protected]
(1 row)

SELECT terakhir menunjukkan email yang kembali seperti semula, dan pola ini menjadi kebiasaan yang menyelamatkan pada pemeliharaan data, yaitu membuka transaksi, menjalankan perubahan, memeriksa, lalu memilih COMMIT atau ROLLBACK secara sadar. Perhatikan bahwa kata “contoh” pada alamat email sengaja mengganti domain aslinya sebagai latihan pembatalan.

Transaksi di dalam psql#

psql menyediakan penanda status pada prompt-nya saat transaksi terbuka, dan mode satu tembakan melalui -c menjalankan seluruh pernyataannya dalam satu transaksi secara bawaan, sehingga kegagalan di tengah -c berisi beberapa pernyataan tetap membatalkan seluruhnya. Flag -1 atau --single-transaction memberi perilaku serupa pada -f yang membaca berkas.

bash
# beberapa pernyataan dalam satu tembakan bersifat satu transaksi
psql -U postgres -d perpustakaan -c "UPDATE anggota SET aktif = TRUE WHERE id = 2; UPDATE anggota SET email = '[email protected]' WHERE id = 2;"
psql -U postgres -d perpustakaan -c "SELECT nama, aktif, email FROM anggota WHERE id = 2;"
text Keluaran
UPDATE 1
UPDATE 1
     nama     | aktif |      email
--------------+-------+------------------
 Budi Santoso | t     | [email protected]
(1 row)

Kedua UPDATE dijalankan sebagai satu unit, dan pola ini menjelaskan mengapa blok penyiapan dataset pada seluruh jalur ini aman diulang, karena kegagalan di tengah berkas penyiapan tidak menyisakan tabel setengah jadi.

Transaksi pada lapisan koneksi#

Kebiasaan transaksi berlanjut ke lapisan aplikasi, karena driver biasanya menjalankan setiap pernyataan dalam autocommit sampai aplikasi mematikannya secara eksplisit. Status yang paling perlu diwaspadai adalah idle in transaction, yaitu koneksi yang membuka transaksi lalu diam menunggu, karena kuncinya tetap dipegang dan versi lama baris tidak dibersihkan selama keadaan itu berlangsung.

Koneksinya ditutup atau dikembalikan ke kolam saat transaksi masih terbuka juga berbahaya, karena server menahan unit kerjanya sampai batas waktu yang ditetapkan idle_in_transaction_session_timeout. Detail pengaturan ini menyusul pada modul administrasi, sedangkan kebiasaan yang dibangun sejak sini adalah menutup unit kerja secepat pekerjaannya selesai, baik dengan COMMIT maupun ROLLBACK.

Kesalahan umum#

Kesalahan pertama adalah lupa membuka BEGIN pada rangkaian pernyataan yang saling bergantung, sehingga kegagalan di tengah meninggalkan keadaan setengah jadi yang tidak terdeteksi. Kesalahan kedua adalah transaksi yang terbuka terlalu lama sambil menunggu konfirmasi manusia, yang menahan baris yang dikuncinya dan menumpuk versi lama di seluruh server.

Kesalahan ketiga adalah mengira ROLLBACK memulihkan perubahan transaksi sebelumnya yang sudah di-COMMIT, padahal pembatalannya hanya menjangkau transaksi yang sedang terbuka, dan pemulihan lintas waktu adalah wilayah backup pada modul administrasi. Kesalahan keempat adalah COMMIT secara refleks tanpa memeriksa status pernyataan, karena angka baris yang berubah tidak sesuai harapan adalah sinyal yang dibaca sebelum menetapkan.

Ringkasan#

  • Tanpa BEGIN, setiap pernyataan berjalan dalam autocommit, dan BEGIN menahan penetapan sampai COMMIT atau ROLLBACK.
  • Penulisnya melihat perubahan yang belum ditetapkan, sedangkan sesi lain menunggu COMMIT sesuai isolation level-nya.
  • Pola aman pemeliharaan adalah buka, ubah, periksa, lalu tetapkan atau batalkan secara sadar.
  • Mode -c dengan beberapa pernyataan serta -f dengan -1 menjalankan unitnya sebagai satu transaksi.

Referensi#