Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Memahami Masalah Baca Kotor dengan SQL Server

Salah satu masalah paling umum yang terjadi saat menjalankan transaksi bersamaan adalah masalah Dirty Read. Pembacaan kotor terjadi ketika satu transaksi diizinkan untuk membaca data yang sedang dimodifikasi oleh transaksi lain yang berjalan secara bersamaan tetapi belum melakukan sendiri.

Jika transaksi yang mengubah data dilakukan sendiri, masalah pembacaan kotor tidak terjadi. Namun jika transaksi yang mengubah data dibatalkan setelah transaksi lain membaca data, transaksi terakhir memiliki data kotor yang sebenarnya tidak ada.

Seperti biasa, pastikan Anda didukung dengan baik sebelum bereksperimen dengan kode baru. Lihat artikel ini tentang mencadangkan database MS SQL jika Anda tidak yakin.

Mari kita pahami ini dengan bantuan sebuah contoh. Misalkan kita memiliki tabel bernama 'Produk' yang menyimpan id, nama, dan ItemsinStock untuk produk tersebut.

Tabelnya terlihat seperti ini:

[id tabel=20 /]

Misalkan Anda memiliki sistem online di mana pengguna dapat membeli produk dan melihat produk secara bersamaan. Perhatikan gambar berikut.

Pertimbangkan skenario di mana pengguna mencoba membeli produk. Transaksi 1 akan melakukan tugas pembelian untuk pengguna. Langkah pertama dalam transaksi adalah memperbarui ItemsinStock.

Sebelum transaksi, ada 12 item dalam stok; transaksi akan memperbarui ini ke 11. Transaksi sekarang akan berkomunikasi dengan gateway penagihan eksternal.

Jika pada saat ini, transaksi lain, katakanlah Transaksi 2, membaca ItemsInStock untuk laptop, itu akan membaca 11. Namun, jika kemudian, pengguna di belakang Transaksi 1 ternyata tidak memiliki cukup dana di akunnya, Transaksi 1 akan digulirkan kembali dan nilai untuk kolom ItemsInStock akan kembali ke 12.

Namun, Transaksi 2 memiliki 11 sebagai nilai untuk kolom ItemsInStock. Ini adalah data kotor dan masalahnya disebut masalah baca kotor.

Contoh Kerja Soal Baca Kotor

Mari kita lihat masalah baca kotor dalam tindakan di SQL Server. Seperti biasa, pertama, mari buat tabel kita dan tambahkan beberapa data dummy ke dalamnya. Jalankan skrip berikut di server database Anda.

CREATE DATABASE pos;

USE pos;

CREATE TABLE products
(
	Id INT PRIMARY KEY,
	Name VARCHAR(50) NOT NULL,
	ItemsinStock INT NOT NULL

)

INSERT into products

VALUES 
(1, 'Laptop', 12),
(2, 'iPhone', 15),
(3, 'Tablets', 10)

Sekarang, buka dua contoh studio manajemen server SQL secara berdampingan. Kami akan menjalankan satu transaksi di setiap kasus ini.

Tambahkan skrip berikut ke instance pertama SSMS.

USE pos;

SELECT * FROM products

-- Transaction 1

BEGIN Tran

UPDATE products set ItemsInStock = 11
WHERE Id = 1

-- Billing the customer
WaitFor Delay '00:00:10'
Rollback Transaction

Dalam skrip di atas, kami memulai transaksi baru yang memperbarui nilai untuk kolom "ItemsInStock" dari tabel produk di mana Id adalah 1. Kami kemudian mensimulasikan penundaan untuk penagihan pelanggan dengan menggunakan fungsi 'Tunggu' dan 'Tunda'. Penundaan 10 detik telah diatur dalam skrip. Setelah itu, kita tinggal roll back transaksinya.

Dalam contoh kedua SSMS, kita cukup menambahkan pernyataan SELECT berikut.

USE pos;

-- Transaction 2

SELECT * FROM products
WHERE Id = 1

Sekarang, pertama jalankan transaksi pertama, yaitu jalankan skrip di SSMS instance pertama, lalu segera jalankan skrip di SSMS instance kedua.

Anda akan melihat bahwa kedua transaksi akan terus dieksekusi selama 10 detik dan setelah itu, Anda akan melihat bahwa nilai kolom 'ItemsInStock' untuk catatan dengan Id 1 masih 12 seperti yang ditunjukkan oleh transaksi kedua. Meskipun transaksi pertama memperbaruinya menjadi 11, menunggu selama 10 detik, dan kemudian mengembalikannya ke 12, nilai yang ditunjukkan oleh transaksi kedua adalah 12, bukan 11.

Apa yang sebenarnya terjadi adalah ketika kami menjalankan transaksi pertama, itu memperbarui nilai untuk kolom 'ItemsinStock'. Kemudian menunggu 10 detik dan kemudian mengembalikan transaksi.

Meskipun kami memulai transaksi kedua segera setelah yang pertama, itu harus menunggu transaksi pertama selesai. Itu sebabnya transaksi kedua juga menunggu selama 10 detik dan mengapa transaksi kedua segera dieksekusi setelah transaksi pertama selesai dieksekusi.

Baca Tingkat Isolasi yang Dikomit

Mengapa transaksi 2 harus menunggu penyelesaian transaksi 1 sebelum dieksekusi?

Jawabannya adalah bahwa tingkat isolasi default antar transaksi adalah "read commited". Tingkat isolasi Read Committed memastikan bahwa data hanya dapat dibaca oleh transaksi jika berada dalam kondisi commit.

Dalam contoh kami, transaksi 1 memperbarui data tetapi tidak melakukan sampai dibatalkan. Inilah sebabnya mengapa transaksi 2 harus menunggu transaksi 1 untuk melakukan data atau mengembalikan transaksi sebelum dapat membaca data.

Sekarang, dalam skenario praktis, kita sering memiliki banyak transaksi yang terjadi pada satu database pada saat yang bersamaan dan kita tidak ingin setiap transaksi harus menunggu gilirannya. Hal ini dapat membuat database sangat lambat. Bayangkan membeli sesuatu secara online dari situs web besar yang hanya dapat memproses satu transaksi dalam satu waktu!

Membaca Data yang Tidak Dikomit

Jawaban untuk masalah ini adalah mengizinkan transaksi Anda bekerja dengan data yang tidak terikat.

Untuk membaca data yang belum dikomit, cukup setel tingkat isolasi transaksi ke "baca tanpa komitmen". Perbarui transaksi 2 dengan menambahkan level isolasi sesuai skrip di bawah ini.

USE pos;

-- Transaction 2
set transaction isolation level read uncommitted

SELECT * FROM products
WHERE Id = 1

Sekarang jika Anda menjalankan transaksi 1 dan kemudian segera menjalankan transaksi 2, Anda akan melihat bahwa transaksi 2 tidak akan menunggu transaksi 1 untuk melakukan data. Transaksi 2 akan langsung membaca data kotor tersebut. Hal ini ditunjukkan pada gambar berikut:

Di sini instance di sebelah kiri menjalankan transaksi 1 dan instance di sebelah kanan menjalankan transaksi 2.

Kami menjalankan transaksi 1 terlebih dahulu yang memperbarui nilai "ItemsinStock" untuk id 1 hingga 11 dari 12 dan kemudian menunggu 10 detik sebelum digulung kembali.

Sementara itu, transaksi w membaca data kotor yaitu 11, seperti yang ditunjukkan pada jendela hasil di sebelah kanan. Karena transaksi 1 dibatalkan, ini bukan nilai sebenarnya dalam tabel. Nilai sebenarnya adalah 12. Coba jalankan transaksi 2 lagi dan Anda akan melihat bahwa kali ini mengambil 12.

Baca tanpa komitmen adalah satu-satunya level isolasi yang memiliki masalah pembacaan kotor. Tingkat isolasi ini paling tidak membatasi dari semua tingkat isolasi dan memungkinkan membaca data yang tidak terikat.

Jelas, ada pro dan kontra untuk menggunakan Read Uncommitted itu tergantung pada aplikasi apa database Anda digunakan. Jelas, itu akan menjadi ide yang sangat buruk untuk menggunakan ini untuk database di belakang sistem ATM dan sistem yang sangat aman lainnya. Namun, untuk aplikasi di mana kecepatan sangat penting (menjalankan toko e-niaga besar) menggunakan Read Uncommitted lebih masuk akal.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Melarikan diri dari kutipan tunggal di SQL Server

  2. Dasar-dasar Pernyataan SQL Server ALTER TABLE

  3. Bagaimana Pernyataan IF Bekerja di SQL Server

  4. Bagaimana Anda membuat pencarian teks lengkap wildcard terkemuka berfungsi di SQL Server?

  5. SIGN() Contoh di SQL Server