![ACID pada Database](https://images.ctfassets.net/7wjlcr9d5ii8/JqBXhaptjKHZLcKulnDxt/f146f34a541265e588b9b8facb314e36/andreiaskirka200701413.jpg?w=450&h=264&fl=progressive&q=100&fm=jpg&fit=thumb&f=faces)
ACID adalah standar operasional transaksi pada database untuk menjamin validitas data meskipun terjadi crash atau error pada system. ACID merupakan aspek yang sangat penting pada transaksi di database untuk memastikan data yang disimpan benar, terpercaya, tanpa anomaly meskipun digunakan secara serentak atau mengalami gangguan pada system. ACID berasal dari singkatan Atomicity, Consistency, Isolation, dan Durability.
Atomicity adalah proses memastikan transaksi pada satu sesi harus dieksekusi semuanya sekaligus atau tidak sama sekali. Ini gunanya adalah agar tidak ada data kotor yang tersisa di database ketika salah satu transaksi gagal tapi transaksi sebelumnya tersimpan di Database. Biar lebih jelas kita simulasikan data berikut:
Table Order
id | order_number | product |
---|---|---|
1 | ORD-123 | kopi |
2 | ORD-321 | susu |
Table Invoice
id | invoice_number | price | order_number |
---|---|---|---|
1 | INV-123 | 5000 | ORD-123 |
2 | INV-321 | 7000 | ORD-321 |
Goalsnya disini adalah kita akan menyimpan data Order dan kemudian otomatis men-generate Invoice. Command yang dilakukan oleh aplikasi biasanya kurang lebih begini:
Insert Order
BEGIN;
INSERT INTO orders (order_number, product) VALUES ('ORD-777', 'teh');
COMMIT;
Insert Invoice
BEGIN;
INSERT INTO invoice (invoice_number, price, order_number) VALUES ('INV-777', 3000, 'ORD-777');
COMMIT;
Jika keduanya berhasil dieksekusi mungkin semuanya baik-baik saja. Tetapi misalnya ketika setelah berhasil eksekusi insertion Order, servernya crash, error, atau ada bugs yang membuat algoritmanya terhenti di tengah jalan. Ordernya jadi tetap tersimpan tapi tanpa Invoice. Ini tentu akan menyisakan data kotor. Untuk itu kita perlu membuat transaksi di atas menjadi Atomicity.
BEGIN;
INSERT INTO orders (order_number, product) VALUES ('ORD-777', 'teh');
INSERT INTO invoice (invoice_number, price, order_number) VALUES ('INV-777', 3000, 'ORD-777');
COMMIT;
Sekarang misalkan servernya crash atau error di tengah jalan setelah insert order dan sebelum insert invoice, maka data Order yang telah berhasil dieksekusi sebelumnya ga akan tersimpan di database karena commit database hanya bisa terjadi ketika kedua transaksi selesai dieksekusi. Ga ada lagi data yang ter-commit setengah-setengah.
Consistency maksudnya adalah database harus memastikan data yang disimpan sesuai dengan rules yang dibuat, meliputi constraints, trigger, cascades, atau kombinasi sejenisnya. Contoh sederhananya misalkan kita memiliki data dengan rules seperti berikut:
- Table Product dengan kolom id, product_code, name, category, created_date;
- Kolom product_code tiap baris harus unik;
- Kolom category memiliki pilihan: Baju, Celana, dan Sepatu;
- Tiap menambahkan data product baru, akan menyimpan tanggal pembuatan pada kolom created_date;
Contoh pelanggaran Consistency berdasarkan rules di atas adalah seperti berikut:
Table Product
id | product_code | name | category | created_date |
---|---|---|---|---|
1 | PRD-001 | jeans biru | celana | 2023-01-24 10:00:01 |
2 | PRD-001 | baju SD | kemeja | null |
Pada tabel di atas, kolom product_code tidak unik. Pada kolom category terdapat value yang tidak sesuai rules yang ditentukan. Value created_date juga tidak terbuat secara otomatis.
Untuk itu kita perlu membuat constraint dan trigger untuk memastikan semua business rules yang kita buat bisa diterapkan pada tabel di atas.
Kita perlu menambahkan constraints Unique Key pada kolom product_code.
alter table "product"
add constraint product_product_code_pk
unique (product_code);
Kita juga perlu menambahkan trigger yang akan menyimpan tanggal pembuatan setiap ada data baru dibuat. Berikut adalah contohnya ketika menggunakan PostgreSql.
CREATE OR REPLACE FUNCTION update_created_date_column()
RETURNS TRIGGER AS
$$
BEGIN
new.created_date = now();
RETURN new;
END;
$$ LANGUAGE 'plpgsql';
CREATE TRIGGER date_creation_at_insert
BEFORE INSERT
ON "product"
FOR EACH ROW EXECUTE PROCEDURE update_created_date_column();
Untuk MySql command-nya seperti ini:
CREATE TRIGGER date_creation_at_insert
BEFORE INSERT
ON product
FOR EACH ROW
BEGIN
SET new.created_date = now();
END;
Terakhir kita akan membuat table product_category yang nantinya akan direferensikan dengan kolom category_id pada table product agar value di kolom category tidak bisa diisi sembarangan.
Table Product Category
id | name |
---|---|
1 | Baju |
2 | Celana |
3 | Sepatu |
Sekarang semuanya sudah sesuai dengan rules yang dibuat. Database akan menghandle rules tersebut setiap kita melakukan transaksi. Jika ada yang ga sesuai rules maka akan divalidasi oleh database.
Table Product
id | product_code | name | category_id | created_date |
---|---|---|---|---|
1 | PRD-001 | jeans biru | 2 | 2023-01-24 10:00:01 |
2 | PRD-002 | baju SD | 1 | 2023-01-24 10:00:01 |
Untuk bahasan tentang Isolation gw bahas terpisah pada tulisan ACID pada Database: Isolation karena terlalu kompleks kalau digabung di sini.
Durability adalah memastikan data yang berhasil di-commit itu akan disimpan secara permanen. Permanen disini maksudnya adalah data yang disimpan tidak akan expire dalam jangka waktu tertentu, dan datanya tidak akan hilang ketika server direstart, crash, atau mengalami gangguan lainnya. Ini berbeda dengan database yang bersifat in-memory seperti H2 atau database yang bisa menyimpan value dalam jangka waktu tertentu seperti Redis. Database yang memenuhi unsur Durability pada ACID akan menyimpan data pada directory tertentu di disk server. Kalau menggunakan PostgreSql kita bisa melakukan eksekusi query show data_directory;
atau pada MySql dengan query show variables like 'datadir'
untuk melihat lokasi tempat di direktori mana data yang kita commit itu disimpan. Ini adalah bagian dari ACID yang paling gampang dipahami😎.