Tutorial Transaction pada Database Relational Untuk Processing Data

Gunakan Transaction pada Backend apabila memiliki beberapa proses sekaligus, ini penting!

Hudya
5 min readSep 26, 2020

Hello semua, Kiddy disini dan bagaimana kabarnya? Mohon maaf nih saya menghilang cukup lama karena harus fokus skripsit terlebih dahulu, sekarang saya sudah resmi lulus sebagai mahasiswa Politeknik Negeri Jakarta~

Setelah blog saya cukup sepi, saya sempet kepikiran mau buat materi apa lagi ya? Nah berhubung saya masih inget ada materi yang belom dishare insightnya, pada hari ini spesial saya akan berbagi materi tentang Transaction pada Database Relasional, sebenernya sih saya maunya memberi Insight ini pada Flask Python. Namun, sebelum jauh masuk ke code, saya rasa saya perlu berbagi insight dari yang dasar terlebih dahulu, tujuannya biar teman-teman ngga bingung sama fundamentalnya hehehe.

Oke, ngomongin soal database tentu aja sebagai backend developer kita pernah menghadapi kasus yang merubah data pada beberapa table secara bersamaan dalam satu request dari frontend. Kasus sederhananya begini:

  1. Kita select dari table A where id = x
  2. Kita update table A where id = x
  3. Kita select dari table B where id = y
  4. kita update table B where id = y
  5. Kita insert data ke table C sebanyak 3 data

Nah ini adalah contoh kasus sederhana yang tepat dalam menggunakan transaction. Sekarang bayangkan, ketika kamu sedang sampai diproses kelima, namun ada error, bisa jadi karena kamu lupa ada column yang tidak boleh kosong tapi kamu malah lempar data kosong. Nah sayangnya proses nomor 2 dan 4 sudah terjadi, artinya ketika terjadi error pada nomor 5, data x dan y sudah berubah dong? Padahal kan proses kelima belom selesai, nah tugas backend adalah mencegah hal itu terjadi, kalo ada error ditengah jalan, maka semua yang telah terjadi harus kembali pada kenangan masa lalu (cielah), alias ROLLBACK ke state atau keadaan sebelumnya dimana kejadiannya harus sebelum proses nomor 1 dijalankan.

Nah si database transaction ini mengenal konsep ACID, yaitu:

src: https://www.youtube.com/watch?v=5Pia4UFuMKo

A stands for Atomic yang artinya, setiap perubahan data harus berhasil atau tidak sama sekali.

C stands for Consistent yang artinya, data harus dalam keadaan konsisten pada saat sebelum dan sesudah transaction.

I stands for Isolated yang artinya, Ngga boleh ada proses yang bisa ngerubah data itu ketika transaction sedang berjalan.

D stands for Durable yang artinya, setiap perubahan yang dibuat sama si transaction harus terus ada alias harus berubah lah intinya.

Nah kita akan mulai dengan mencoba database transactions. Disini saya menggunakan MySQL 8.0 yah~

Pertama kita buat dulu databasenya.

CREATE DATABASE nyoba_transaction;

Sekarang kita wajib use database kita:

USE nyoba_transaction;

Dan sekarang kita buat table yang akan kita gunakan terlebih dahulu.

CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name varchar(200) NOT NULL, email varchar(200) NOT NULL );CREATE TABLE jobs (id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, name varchar(200) NOT NULL, finished_at DATETIME, created_at DATETIME DEFAULT(now()), FOREIGN KEY (user_id) REFERENCES users(id));CREATE TABLE logs (id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, job_id INT NOT NULL, message text, created_at DATETIME DEFAULT(now()), FOREIGN KEY (user_id) REFERENCES users(id), FOREIGN KEY (job_id) REFERENCES jobs(id));

Oke kita udah buat table kebutuhan kita nih, nah sekarang gimana kasusnya bang?

Kita asumsikan kita akan punya 1 pengguna, pengguna tersebut akan membuat satu jobs, nah setelah jobs tersebut diinsert ke database, table logs juga akan diisi untuk menandakan pekerjaan sedang berjalan dan mencatat setiap pesan. Log akan mencatat 3 state, job dimulai, job memproses, job selesai. Sesudah job selesai kamu akan mengupdate job tersebut untuk mengisi finished_at, tapi entah mengapa kamu malah melakukan kesalahan, finished_at kamu isi sebuah string. Jadi ada 4 proses sekaligus dalam sebuah request ke database.

Sekarang kita mulai eksekusi transactionnya.

Pertama insert dulu data ke table users, kalo mau cepet sih boleh coppas dibawah, tapi ganti dulu ya, saya agak narsis soalnya.

INSERT INTO users VALUES (null, 'Hudya Kece', 'hudya@hey.com');

Nah ini hasilnya:

mysql> select * from users;
+----+------------+---------------+
| id | name | email |
+----+------------+---------------+
| 1 | Hudya Kece | hudya@hey.com |
+----+------------+---------------+
1 row in set (0.00 sec)

Oke let’s begin! Kita mulai jalankan dulu transactionnya, dimulai dengan cara:

START TRANSACTION;

Kalau sudah kita coba yuk untuk insert data baru.

INSERT INTO users values (null, "Kiddy", "kiddy@mail.com");

Sekarang coba SELECT.

mysql> SELECT * FROM users;
+----+------------+----------------+
| id | name | email |
+----+------------+----------------+
| 1 | Hudya Kece | hudya@hey.com |
| 2 | Kiddy | kiddy@mail.com |
+----+------------+----------------+
2 rows in set (0.00 sec)

Lalu kita Rollback.

ROLLBACK;

Kita ngintip lagi ke MySQL

mysql> SELECT * FROM users;
+----+------------+---------------+
| id | name | email |
+----+------------+---------------+
| 1 | Hudya Kece | hudya@hey.com |
+----+------------+---------------+
1 row in set (0.00 sec)

Hilang? Tentu, kan kita rollback xixixi. Lalu, biar caranya masuk seperti apa? Instead of ROLLBACK, kita gunakan COMMIT.

START TRANSACTION;
INSERT INTO users values (null, "Kiddy", "kiddy@mail.com");
SELECT * FROM users;
COMMIT;

Gimana terkait kasus ini?

Kita asumsikan kita akan punya 1 pengguna, pengguna tersebut akan membuat satu jobs, nah setelah jobs tersebut diinsert ke database, table logs juga akan diisi untuk menandakan pekerjaan sedang berjalan dan mencatat setiap pesan. Log akan mencatat 3 state, job dimulai, job memproses, job selesai. Sesudah job selesai kamu akan mengupdate job tersebut untuk mengisi finished_at, tapi entah mengapa kamu malah melakukan kesalahan, finished_at malah kamu isi sebuah string, tugasmu adalah merollbacknya!

Mohon kerjakan perbaris ya kalau lewat CLI MySQL, kalau lewat PHP My Admin belom saya coba sih xixixi.

-- Memulai transaksi
START TRANSACTION;
-- Insert data ke table jobs
INSERT INTO jobs values (null, 1, "Job percobaan", null, now());
-- Ngintip dulu
mysql> SELECT * FROM jobs;
+----+---------+---------------+-------------+---------------------+
| id | user_id | name | finished_at | created_at |
+----+---------+---------------+-------------+---------------------+
| 6 | 1 | Job percobaan | NULL | 2020-09-26 11:34:26 |
+----+---------+---------------+-------------+---------------------+
1 row in set (0.00 sec)
-- Insert baris pertama untuk logs
INSERT INTO logs VALUES (null, 1, 6, "Job dimulai", now());
-- Insert baris kedua untuk logs
INSERT INTO logs VALUES (null, 1, 6, "Job sedang diproses", now());
-- Insert baris ketiga untuk finishing
INSERT INTO logs VALUES (null, 1, 6, "Job selesai", now());
-- Update untuk menandakan selesai
UPDATE jobs SET finished_at = "SALAH" where id = 6;

UPS TERNYATA BARIS TERAKHIR SALAH, KAMU HARUS MEMBUAT TRANSAKSINYA UNTUK ROLLBACK!

ROLLBACK;

Sekarang kalau kita select dari jobs maka yang terjadi adalah:

mysql> SELECT * FROM jobs;
Empty set (0.00 sec)

Gampang bukan? Mungkin terlihat membingungkan, tapi saya mau sharing ini agar agan-agan paham fungsional dasarnya terlebih dahulu, next, saya akan beritahu caranya menggunakan transaction pada Flask, stay tune!

--

--

Hudya
Hudya

Written by Hudya

Which is more difficult, coding or counting? Not both of them, the difficult one is sharing your knowledge to people without asking the payment.

No responses yet