
Foto oleh panumas nikhomkhai via Pexels
Isolation level menentukan seberapa ketat SQL Server mengisolasi satu transaksi dari transaksi lain yang berjalan bersamaan, dan pilihan level ini secara langsung memengaruhi jenis locking yang terjadi di belakang layar serta anomali data apa saja yang mungkin muncul.
SQL Server menyediakan beberapa isolation level standar: READ UNCOMMITTED (paling longgar, bisa membaca data yang belum di-commit), READ COMMITTED (default, hanya membaca data yang sudah commit), REPEATABLE READ (mencegah data berubah selama transaksi berjalan), dan SERIALIZABLE (paling ketat, mencegah baris baru muncul di tengah transaksi).
Memilih isolation level yang tepat adalah soal menyeimbangkan antara konsistensi data yang dibutuhkan aplikasi dan dampaknya terhadap concurrency, karena semakin ketat isolasinya, semakin besar pula kemungkinan transaksi lain harus menunggu.
READ UNCOMMITTED dan Masalah Dirty Read
READ UNCOMMITTED berisiko dirty read
READ COMMITTED sebagai Default yang Seimbang
READ COMMITTED adalah default SQL Server
REPEATABLE READ Mencegah Perubahan Saat Transaksi Berjalan
REPEATABLE READ menjamin baris yang sudah dibaca tidak berubah
SERIALIZABLE sebagai Level Paling Ketat
SERIALIZABLE mencegah phantom read
Perbedaan READ COMMITTED SNAPSHOT dengan Isolation Level Tradisional
RCSI menghindari blocking dengan membaca versi baris dari tempdb
Pada isolation level READ COMMITTED tradisional, pembacaan data akan memakai shared lock sesaat dan harus menunggu jika baris yang sama sedang dikunci exclusive lock oleh transaksi lain yang belum commit, sehingga sering menimbulkan blocking pada sistem dengan trafik baca-tulis yang padat. READ_COMMITTED_SNAPSHOT (RCSI) mengubah mekanisme ini menjadi berbasis row versioning.
Dengan RCSI aktif, setiap kali baris diubah, SQL Server menyimpan versi baris sebelumnya di tempdb, sehingga transaksi lain yang membaca baris tersebut pada waktu bersamaan akan diarahkan membaca versi lama itu alih-alih menunggu lock dilepas; pembaca tidak lagi memblokir atau diblokir oleh penulis, meskipun data yang dibaca mungkin sedikit lebih lama dibanding versi yang sedang diproses transaksi lain.
Konsekuensi mengaktifkan RCSI adalah peningkatan beban pada tempdb karena setiap versi baris harus disimpan sementara, sehingga kapasitas dan performa tempdb perlu dipastikan memadai sebelum fitur ini diaktifkan di database production, dan perilaku ini berbeda dari SNAPSHOT isolation level yang harus diaktifkan secara eksplisit per sesi melalui SET TRANSACTION ISOLATION LEVEL SNAPSHOT.
Fenomena Phantom Read pada Isolation Level REPEATABLE READ
REPEATABLE READ tidak mencegah baris baru muncul di antara dua pembacaan rentang
Phantom read terjadi ketika sebuah transaksi menjalankan query dengan kondisi filter yang sama dua kali, namun mendapatkan jumlah baris yang berbeda karena transaksi lain berhasil menyisipkan atau menghapus baris yang memenuhi kondisi filter tersebut di antara kedua pembacaan. Isolation level REPEATABLE READ mencegah non-repeatable read dengan mengunci baris-baris yang sudah dibaca agar tidak bisa diubah transaksi lain, tetapi kunci tersebut hanya berlaku pada baris yang sudah ada, bukan pada rentang nilai secara keseluruhan.
Akibatnya, REPEATABLE READ tidak mencegah transaksi lain menyisipkan baris baru yang memenuhi kondisi WHERE yang sama, sehingga query agregasi seperti COUNT(*) atau SUM() yang dijalankan ulang di dalam transaksi yang sama bisa menghasilkan angka yang berbeda meskipun seluruh baris yang dibaca sebelumnya tidak berubah nilainya sama sekali.
SERIALIZABLE adalah isolation level paling ketat yang mengatasi masalah ini dengan menerapkan range lock pada rentang nilai yang dicakup kondisi WHERE, bukan hanya pada baris yang sudah ada, sehingga transaksi lain yang mencoba menyisipkan baris baru ke dalam rentang yang dikunci akan diblokir sampai transaksi pertama selesai. Konsekuensinya, SERIALIZABLE memiliki risiko blocking dan deadlock yang jauh lebih tinggi dibanding isolation level lain, sehingga pemakaiannya dibatasi pada operasi yang benar-benar membutuhkan konsistensi rentang yang ketat.
Snapshot Isolation dan Deteksi Update Conflict Dibanding Serializable
SNAPSHOT isolation mendeteksi update conflict dan membatalkan transaksi, bukan memblokir
SNAPSHOT isolation level harus diaktifkan terlebih dahulu di level database melalui ALLOW_SNAPSHOT_ISOLATION ON, dan serupa dengan RCSI karena sama-sama memakai row versioning dari tempdb, namun bedanya SNAPSHOT diaktifkan eksplisit per sesi dengan SET TRANSACTION ISOLATION LEVEL SNAPSHOT, bukan menjadi default otomatis seperti RCSI.
Perbedaan penting dengan SERIALIZABLE adalah cara menangani konflik tulis: SERIALIZABLE mencegah konflik dengan memblokir transaksi lain lewat range lock, sedangkan SNAPSHOT membiarkan kedua transaksi berjalan tanpa blocking namun akan membatalkan transaksi yang belakangan commit jika baris yang sama ternyata sudah diubah transaksi lain sejak baris itu dibaca, ditandai error 3960 yang mengharuskan aplikasi melakukan retry transaksi. Model optimistik semacam ini cocok untuk beban kerja dengan konflik tulis yang jarang terjadi, karena menghindari blocking pada kondisi normal namun tetap membutuhkan logika retry di sisi aplikasi untuk menangani kegagalan yang sesekali muncul.
Kesalahan Umum yang Sering Terjadi
Memakai READ UNCOMMITTED untuk Data Finansial
Menggunakan READ UNCOMMITTED pada laporan keuangan atau saldo bisa menghasilkan angka yang ternyata berasal dari transaksi yang akhirnya dibatalkan, menyebabkan laporan yang tidak akurat tanpa indikasi error apa pun.
Mengabaikan Dampak Isolation Level Tinggi pada Concurrency
Mengganti isolation level ke SERIALIZABLE di seluruh aplikasi tanpa analisis bisa membuat sistem yang sebelumnya cepat menjadi sangat lambat karena banyak transaksi saling menunggu lock yang dipegang lebih lama.
Tidak Mempertimbangkan Snapshot Isolation sebagai Alternatif
SQL Server juga menyediakan SNAPSHOT isolation yang memakai row versioning alih-alih locking untuk mencegah banyak anomali sekaligus tanpa blocking berlebihan, sebuah opsi yang sering terlewat karena harus diaktifkan eksplisit di level database.
Kapan Pendekatan Ini Tidak Cocok Dipakai
Isolation level yang lebih longgar seperti READ COMMITTED memberikan performa dan concurrency lebih baik, cocok untuk kebanyakan operasi CRUD sehari-hari yang tidak terlalu sensitif terhadap anomali kecil.
Isolation level yang lebih ketat seperti REPEATABLE READ atau SERIALIZABLE memberikan jaminan konsistensi lebih kuat yang dibutuhkan untuk operasi finansial atau laporan kritikal, namun dengan konsekuensi performa yang harus diuji dan dipertimbangkan matang-matang pada sistem dengan trafik tinggi.
Ringkasan
Setiap isolation level menawarkan titik keseimbangan berbeda antara konsistensi data dan performa, mulai dari READ UNCOMMITTED yang paling longgar sampai SERIALIZABLE yang paling ketat. Pilih level berdasarkan seberapa kritikal konsistensi data untuk operasi tertentu, bukan sekadar memakai default atau level paling ketat secara membabi buta di semua tempat.
Seri Belajar SQL Server:
← Sebelumnya: Transaction dan ACID pada SQL Server
→ Selanjutnya: Memahami Deadlock dan Cara Menghindarinya (segera terbit)