ACID

Prinsip **ACID** (akronim dari istilah bahasa Inggris ***a'''tomicity, '''c'''onsistency, '''i'''solation'' dan ***d**urability'') adalah serangkaian sifat dari [[Transaksi basis data|transaksi]] yang terjadi dalam basis data yang menjamin validitas data meskipun terjadi galat, kegagalan daya, dan kerusakan lainnya pada mesin saat basis data beroperasi melakukan transaksi data pada mesin. Dalam konteks [[Pangkalan data|basis data]], suatu ''transaksi'' dimaknai sebagai suatu rangkaian operasi logis pada basis data yang memenuhi sifat ACID. Sebagai contoh, operasi transfer dana dari satu [[rekening bank]] ke rekening bank lain, bahkan apabila melibatkan perubahan pada beberapa data seperti mendebit satu rekening dan mengkredit rekening lain, dihitung sebagai satu transaksi.

Pada tahun 1983,  Andreas Reuter dan Theo Härder menciptakan akronim ''ACID'', yang merupakan modifikasi dari hasil penelitian sebelumnya oleh [[James N. Gray|Jim Gray]] yang pertama menelurkan sifat ''atomicity'' (atomisitas), ''consistency'' (konsistensi), dan ''durability'' (ketahanan) dalam mendeskripsikan suatu transaksi basis data. Heuter dan Härder kemudian menambahkan satu sifat lagi, yaitu ''isolation'' (isolasi). Keempat sifat ini menjadi patokan jaminan keberhasilan transaksi dalam basis data, memengaruhi banyak aspek pengembangan dalam kajian [[Pangkalan data|sistem basis data]].

Menurut Gray dan Reuter, Sistem Manajemen Informasi [[IBM]] telah mengimplementasikan sifat ACID dalam transaksi basis data pada sistemnya sejak tahun 1973 (meskipun akronimnya secara teoretis baru dibuat 1 dekade kemudian).

Selain prinsip ACID, dalam basis data juga dikenal prinsip BASE yang merupakan akronim dari ***b*'asically **a**vailable* (selalu tersedia), ***s**oft state* (berkeadaan tidak tetap), and ***e**ventually consistent* (akan konsisten di akhir). Secara teoretik, prinsip BASE merupakan kebalikan dari prinsip ACID, sebagaimana [[Nomina|kata benda]] yang membentuk akronim merupakan kebalikan dalam [[Kimia|ilmu kimia]] (*basa* dan *asam*). Basis data yang berprinsip ACID mengutamakan konsistensi pada data ketimbang *'ketersediaan** — membuat suatu transaksi akan gagal jika terjadi kesalahan pada langkah mana pun dalam transaksi, sehingga data akan tetap konsisten; sebaliknya, basis data berprinsip BASE mengutamakan **ketersediaan**  data daripada **konsistensi**: ketika terjadi kegagalan dalam transaksi, pengguna tetap dapat mengakses data yang tidak konsisten **untuk sementara** untuk kemudian dibenahi dan dikembalikan. Dalam prinsip BASE, konsistensi data dapat tercapai, tetapi **tidak langsung*', sedang dalam prinsip ACID, konsistensi terjadi secara langsung.

== Karakteristik ==
Reuter dan Härder mendefinisikan masing-masing karakteristik pada prinsip ACID sebagai berikut:

=== Atomisitas (*Atomicity*) ===
Transaksi dalam basis data, yang terjadi menggunakan perintah [[SQL]], sering kali terdiri dari beberapa pernyataan SQL. Prinsip atomisitas menjamin bahwa setiap transaksi diperlakukan sebagai satu "unit" (atom), yang dapat bernilai berhasil atau tidak: jika salah satu pernyataan dalam transaksi gagal diselesaikan, seluruh transaksi gagal dan basis data tidak berubah. Sistem yang berprinsip atomik harus menjamin setiap situasi, termasuk kegagalan daya, kesalahan, dan kerusakan terjadi secara atomik untuk menjaga integritas data. Prinsip atomisitas mencegah pembaruan tidak sempurna (sebagian) pada basis data, yang dapat menyebabkan masalah yang lebih besar ketimbang menolak seluruh transaksi secara langsung. Sebagai konsekuensi, pengguna atau program lain yang sedang mengakses basis data pada saat yang sama tidak akan pernah melihat transaksi yang baru setengah jalan. Pada satu saat, transaksi tersebut belum terjadi, dan pada saat berikutnya, itu transaksi tersebut telah terjadi secara sempurna (atau tidak ada yang terjadi jika transaksi dibatalkan saat sedang berlangsung).

=== Konsistensi (*Consistency*) ===
Prinsip konsistensi memastikan bahwa suatu transaksi hanya dapat membawa basis data dari satu keadaan konsisten ke keadaan konsisten lainnya, sehingga mempertahankan [[Invarian (matematika)|invarian]] (aturan dan batasan) pada basis data. Maksudnya, setiap data yang ditulis ke basis data harus valid sesuai dengan semua aturan dan batasan yang ditetapkan, termasuk kendala (*constraints*), penjalaran (*cascade*), pemicu (*triggers*), dan kombinasi apa pun dari ketiganya. Hal ini mencegah kerusakan basis data akibat transaksi ilegal. Contoh invarian basis data adalah integritas referensial, yang menjamin validitas hubungan antara kunci primer – kunci asing.

=== Isolasi (*Isolation*) ===
Beberapa transaksi seringkali dieksekusi secara serentak (*concurrent*; misalnya, beberapa transaksi membaca dan menulis ke tabel secara bersamaan). Prinsip isolasi memastikan bahwa eksekusi transaksi secara bersamaan dan menjadikan basis data dalam keadaan yang sama seperti jika transaksi dieksekusi secara berurutan. Isolasi adalah tujuan utama dari kontrol keserentakan (*concurrency control*); tergantung pada tingkat isolasi yang digunakan, efek dari transaksi yang tidak lengkap mungkin tidak terlihat oleh transaksi lain.

=== Ketahanan (*Durability*) ===
Ketahanan menjamin bahwa setelah transaksi selesai dilakukan, transaksi tersebut akan bersifat tetap (*committed*) bahkan jika terjadi kegagalan sistem (misalnya, pemadaman listrik atau [[Mogok (komputasi)|mogok]]). Ini biasanya berarti bahwa transaksi yang telah selesai (atau dampaknya) dicatat dalam memori non-volatil.

== Contoh ==
Contoh-contoh berikut memberikan ilustrasi sifat ACID dalam transaksi di suatu basis data perbankan. Dalam contoh ini, tabel basis data memiliki dua kolom, <math>A</math> dan <math>B</math>. Kendala integritas mengharuskan nilai di <math>A</math> dan nilai di <math>B</math> berjumlah 100. Kode [[SQL]] berikut membuat tabel seperti yang dijelaskan di atas:<syntaxhighlight lang="sql">
CREATE TABLE acidtest (A INTEGER, B INTEGER, CHECK (A + B = 100));
</syntaxhighlight>

=== Atomisitas ===

Menggunakan ilustrasi basis data perbankan yang telah disiapkan, terdapat suatu transaksi transfer uang dari rekening A ke rekening B. Transaksi ini terdiri dari dua operasi, yaitu penarikan sejumlah uang dari rekening A dan penyetorannya ke rekening B. Suatu transaksi berhasil yang bersifat atomik terjadi apabila kedua operasi tersebut berhasil secara sempurna. Transaksi tidak bisa dikatakan berhasil sebelum jumlah uang yang ditarik dari rekening A telah ditransfer ke rekening B dalam jumlah yang sama. Transaksi yang atomik memastikan bahwa basis data tetap konsisten, yaitu, uang tidak akan didebet maupun dikredit jika salah satu dari kedua operasi tersebut gagal.

=== Kegagalan konsistensi ===
Konsistensi adalah istilah yang sangat umum, yang menuntut bahwa data harus memenuhi semua aturan validasi. Dalam contoh basis data perbankan sebelumnya, validasi dilakukan dengan memeriksa bahwa . Seluruh aturan validasi harus diperiksa untuk memastikan prinsip konsistensi terpenuhi. Misalkan suatu transaksi mencoba untuk mengurangi sebanyak 10 unit dari <math>A</math> tanpa melakukan perubahan pada <math>B</math>. Karena konsistensi diperiksa setelah setiap transaksi, diketahui bahwa  sebelum transaksi dimulai. Jika transaksi menghapus 10 unit dari <math>A</math> dengan sukses, transaksi tersebut dapat disifati sebagai atomik. Namun, ketika pengecekan validasi dilakukan, ditemukan bahwa , yang tidak konsisten dengan aturan validasi. Dengan demikian, sistem akan membatalkan transaksi dan baris akan dikembalikan ke keadaan sebelum transaksi (*rollback*). Bila sistem menetapkan suatu kendala, pemicu, atau penjalaran lain, tiap operasi perubahan tunggal akan diperiksa dengan cara yang sama sebelum transaksi disahkan/dikomit (*committed*). Masalah serupa dapat muncul dengan kendala lain. Pengguna dapat mensyaratkan tipe data [[bilangan bulat]] untuk <math>A</math> dan <math>B</math>. Jika kita kemudian terdapat transaksi yang memasukkan nilai desimal, semisal 13,5 untuk <math>A</math>, transaksi akan dibatalkan, atau sistem mungkin akan memunculkan peringatan berupa pemicu (jika pengguna membuatnya). Contoh lain dari suatu kendala integritas, adalah suatu kendala yang tidak mengizinkan kita menghapus baris yang kunci utamanya dirujuk oleh setidaknya satu kunci asing di tabel lain.

=== Kegagalan isolasi ===
Misalkan terdapat dua transaksi dijalankan pada saat yang sama, masing-masing mencoba mengubah data yang sama. Salah satu transaksi harus menunggu hingga transaksi lainnya selesai agar isolasi tetap terjaga.

Berikut dua transaksi:

* <math>T_1</math> melakukan operasi transfer 10 unit dari <math>A</math> ke <math>B</math>.
* <math>T_2</math> melakukan operasi transfer 20 unit dari <math>B</math> ke <math>A</math>.

Jika digabungkan, terdapat empat operasi:

# <math>T_1</math> mengurangi 10 unit dari <math>A</math>.
# <math>T_1</math> menambahkan 10 unit ke <math>B</math>.
# <math>T_2</math> mengurangi 20 unit dari <math>B</math>.
# <math>T_2</math> menambahkan 20 unit ke <math>A</math>.

Jika operasi-operasi ini dilakukan secara berurutan, isolasi tetap terjaga, meskipun <math>T_2</math> harus menunggu. Apabila terjadi kegagalan pada <math>T_1</math> di tengah operasi, basis data cukup menghilangkan hasil <math>T_1</math>, dan <math>T_2</math> hanya menggunakan data awal yang valid.

Bila dilakukan penjalinan pada transaksi (tanpa isolasi), urutan tindakan mungkin menjadi:

# <math>T_1</math> mengurangi 10 unit dari <math>A</math>.
# <math>T_2</math> mengurangi 20 unit dari <math>B</math>.
# <math>T_2</math> menambahkan 20 unit ke <math>A</math>.
# <math>T_1</math> menambahkan 10 unit ke <math>B</math>.

Pada skema ini, misalkan terjadi kegagalan pada langkah ke-4, yaitu saat <math>T_1</math> mencoba memodifikasi <math>B</math>. Ketika <math>T_1</math> gagal, <math>T_2</math> sudah lebih dahulu mengubah nilai <math>A</math>. Akibatnya, nilai <math>A</math> tidak dapat dikembalikan ke keadaan sebelum <math>T_1</math> dimulai tanpa sekaligus membatalkan perubahan sah yang telah dilakukan oleh <math>T_2</math>, yang akan menyebabkan basis data menjadi tidak konsisten. Hal ini dikenal sebagai *write-to-write contention* (konflik penulisan ganda), karena dua transaksi mencoba menulis ke isian data yang sama. Umumnya, masalah ini dapat diselesaikan dengan melakukan pengembalian ke status baik termutakhir yang diketahui, membatalkan transaksi <math>T_1</math> yang gagal, dan memulai kembali transaksi <math>T_2</math>  berdasarkan status baik termutakhir.

=== Kegagalan daya tahan ===
Asumsikan suatu transaksi yang mentransfer 10 unit dari <math>A</math> ke <math>B</math>. Pertama, transaksi tersebut menghapus 10 unit dari <math>A</math>, lalu menambahkan 10 unit ke <math>B</math>. Pada titik ini, pengguna diberi tahu bahwa transaksi tersebut berhasil. Namun, pada keadaan fisik cakram perangkat, perubahan tersebut masih mengantre di *disk buffer* (penyimpan sementara), menunggu untuk dikomit ke disk. Bila terjadi pemadaman listrik, perubahan hilang, tetapi pengguna berasumsi bahwa perubahan tersebut sudah masuk ke dalam penyimpanan. Ini adalah salah satu bentuk kegagalan dalam prinsip ketahanan.

== Implementasi ==
Pemrosesan transaksi sering kali memerlukan serangkaian operasi yang rentan terhadap kegagalan karena sejumlah alasan. Misalnya, sistem mungkin tidak memiliki ruang tersisa pada *disk drive*-nya, atau mungkin telah menggunakan semua alokasi waktu CPU yang tersedia. Terdapat dua jenis teknik yang populer menghadapi potensi kegagalan: *write-ahead logging* dan *shadow paging*. Dalam kedua kasus tersebut, kunci (*lock*) harus diperoleh pada semua informasi yang akan diubah dan mungkin pada semua data yang dapat dibaca juga (tergantung tingkatan proses isolasi pada data tersebut). Dalam *write ahead logging*, penjaminan ketahanan dilakukan dengan menulis calon perubahan data (*prospective changes*) ke log persisten sebelum dilakukan perubahan dalam basis data. Hal tersebut memungkinkan basis data untuk kembali ke keadaan konsisten jika terjadi kegagalan sistem. Dalam *page shadowing*, pembaruan diterapkan pada salinan parsial basis data, dan salinan baru diaktifkan ketika transaksi dikomit.

=== Penguncian vs. multiversi ===
Banyak basis data mengandalkan sistem penguncian (*locks*) untuk memenuhi prinsip ACID. *Penguncian* bermakna suatu transaksi menandai data yang sedang diakses untuk memberi tahu DBMS agar tidak mengizinkan transaksi lain mengaksesnya hingga transaksi pertama berstatus berhasil atau gagal. Status penguncian harus selalu diperoleh  dari DBMS sebelum transaksi memproses data, termasuk data yang dibaca tetapi tidak diubah. Transaksi non-trivial biasanya membutuhkan sejumlah besar penguncian, yang mengakibatkan *overhead* yang substansial serta memblokir transaksi lain. Misalnya, jika pengguna X menjalankan transaksi yang harus membaca baris data yang ingin diubah oleh pengguna Y, pengguna X harus menunggu hingga transaksi pengguna Y selesai. Penguncian dua fase (*two-phase locking*) sering diterapkan untuk menjamin isolasi penuh.

Alternatif untuk penguncian adalah kontrol keserentakan multiversi (*multiversion concurrency control*), yakni basis data menyediakan versi data sebelumnya yang belum dimodifikasi untuk tiap transaksi, yang mungkin sedang dimodifikasi oleh transaksi aktif lainnya. Hal ini memungkinkan pengguna untuk melakukan operasi baca (*read*) tanpa memerlukan kunci, yaitu, transaksi penulisan tidak perlu memblokir transaksi pembacaan, dan pengguna yang melakukan operasi baca tidak memblokir pengguna yang melakukan operasi tulis. Misalnya, ketika transaksi pengguna X meminta data yang dimodifikasi oleh pengguna Y, basis data menyediakan X dengan versi data yang ada sebelum pengguna Y memulai transaksinya. Pengguna X mendapatkan tampilan basis data yang konsisten meskipun pengguna lain mengubah data. Salah satu implementasi, disebut isolasi snapshot, memberlakukan prinsip isolasi dengan lebih longgar.

=== Transaksi terdistribusi ===
Menjamin sifat ACID dalam transaksi terdistribusi di seluruh basis data terdistribusi merupakan aksi yang kompleks, karena tidak ada satu simpul pun yang bertanggung jawab atas semua data yang memengaruhi transaksi. Dapat terjadi kegagalan dalam koneksi jaringan, atau satu simpul mungkin berhasil menyelesaikan bagiannya dari transaksi dan kemudian diminta untuk mengembalikan perubahannya karena kegagalan pada simpul lain. Protokol komit dua fase (*two-phase commit protocol''; berbeda dengan penguncian dua fase) menyediakan proses atomik untuk transaksi terdistribusi dengan memastikan bahwa setiap peserta dalam transaksi memberikan tanda setuju apakah transaksi harus dikomit atau tidak. Secara singkat, pada fase pertama, satu simpul (koordinator) menginterogasi simpul lain (peserta), dan hanya ketika semua menjawab bahwa mereka siap, koordinator, pada fase kedua, melakukan komit terhadap transaksi.

## Lihat juga

* Interkoneksi Sistem Terbuka
* CRUD

## Referensi