dapat dibuat serial tingkat isolasi memberikan perlindungan lengkap dari efek konkurensi yang dapat mengancam integritas data dan menyebabkan hasil kueri yang salah. Menggunakan isolasi serializable berarti bahwa jika transaksi yang dapat ditunjukkan untuk menghasilkan hasil yang benar tanpa aktivitas bersamaan, transaksi tersebut akan terus berjalan dengan benar saat bersaing dengan kombinasi transaksi bersamaan.
Ini adalah jaminan yang sangat kuat , dan salah satu yang mungkin cocok dengan ekspektasi isolasi transaksi intuitif dari banyak programmer T-SQL (meskipun sebenarnya, relatif sedikit dari ini yang akan secara rutin menggunakan isolasi serial dalam produksi).
Standar SQL mendefinisikan tiga tingkat isolasi tambahan yang menawarkan ACID yang jauh lebih lemah jaminan isolasi daripada serializable, sebagai imbalan untuk konkurensi yang berpotensi lebih tinggi dan potensi efek samping yang lebih sedikit seperti pemblokiran, kebuntuan, dan pembatalan commit-time.
Tidak seperti isolasi serial, tingkat isolasi lainnya didefinisikan semata-mata dalam hal fenomena konkurensi tertentu yang mungkin diamati. Level isolasi standar terkuat berikutnya setelah serializable bernama repeatable read . Standar SQL menetapkan bahwa transaksi pada tingkat ini memungkinkan fenomena konkurensi tunggal yang dikenal sebagai hantu .
Seperti yang telah kita lihat sebelumnya, perbedaan penting antara makna intuitif umum dari properti transaksi ACID dan kenyataan, fenomena hantu mencakup rentang perilaku yang lebih luas daripada yang sering diapresiasi.
Pos dalam seri ini melihat jaminan sebenarnya yang diberikan oleh pembacaan berulang tingkat isolasi, dan menunjukkan beberapa perilaku terkait hantu yang dapat ditemui. Untuk mengilustrasikan beberapa poin, kita akan mengacu pada contoh kueri sederhana berikut, di mana tugas sederhananya adalah menghitung jumlah total baris dalam sebuah tabel:
SELECT COUNT_BIG(*) FROM dbo.SomeTable;
Baca yang Dapat Diulang
Satu hal yang aneh tentang tingkat isolasi baca berulang adalah tidak sebenarnya menjamin bahwa pembacaan dapat diulang , setidaknya dalam satu pengertian yang umum dipahami. Ini adalah contoh lain di mana makna intuitif saja bisa menyesatkan. Menjalankan kueri yang sama dua kali dalam transaksi baca berulang yang sama memang dapat memberikan hasil yang berbeda.
Selain itu, implementasi SQL Server dari pembacaan berulang berarti bahwa satu pembacaan dari sekumpulan data mungkin melewatkan beberapa baris yang secara logis harus dipertimbangkan dalam hasil kueri. Meskipun spesifik untuk implementasi, perilaku ini sepenuhnya sejalan dengan definisi pembacaan berulang yang terdapat dalam standar SQL.
Hal terakhir yang ingin saya perhatikan dengan cepat sebelum mempelajari detailnya, adalah bahwa pembacaan berulang di SQL Server tidak memberikan tampilan data secara tepat waktu.
Bacaan yang Tidak Dapat Diulang
Tingkat isolasi baca berulang memberikan jaminan bahwa data tidak akan berubah selama masa transaksi setelah dibaca untuk pertama kalinya.
Ada beberapa seluk-beluk yang terkandung dalam definisi itu. Pertama, memungkinkan data berubah setelah transaksi dimulai tetapi sebelum data pertama diakses. Kedua, tidak ada jaminan bahwa transaksi akan benar-benar menemukan semua data yang memenuhi syarat secara logis. Kita akan melihat contoh keduanya segera.
Ada satu pendahuluan lain yang perlu kita selesaikan dengan cepat, yang berkaitan dengan contoh kueri yang akan kita gunakan. Sejujurnya, semantik kueri ini agak kabur. Dengan risiko terdengar sedikit filosofis, apa artinya menghitung jumlah baris dalam tabel? Haruskah hasilnya mencerminkan keadaan tabel seperti pada titik waktu tertentu? Haruskah titik waktu ini menjadi awal atau akhir transaksi, atau yang lainnya?
Ini mungkin tampak agak rewel, tetapi pertanyaannya valid di basis data apa pun yang mendukung pembacaan dan modifikasi data secara bersamaan. Mengeksekusi kueri contoh kami dapat memakan waktu lama yang sewenang-wenang (mengingat tabel yang cukup besar, atau kendala sumber daya misalnya) sehingga perubahan bersamaan tidak hanya mungkin, tetapi juga tidak dapat dihindari .
Masalah mendasar di sini adalah potensi fenomena konkurensi yang disebut sebagai hantu dalam standar SQL. Saat kami menghitung baris dalam tabel, transaksi bersamaan lainnya mungkin menyisipkan baris baru di tempat yang telah kami periksa, atau ubah baris yang belum kita periksa sedemikian rupa sehingga bergerak ke tempat yang telah kita lihat. Orang sering menganggap hantu sebagai baris yang mungkin muncul secara ajaib ketika dibaca untuk kedua kalinya, dalam pernyataan terpisah, tetapi efeknya bisa jauh lebih halus dari itu.
Contoh Sisipan Bersamaan
Contoh pertama ini menunjukkan bagaimana penyisipan bersamaan dapat menghasilkan tidak dapat diulang membaca dan/atau mengakibatkan baris dilewati. Bayangkan bahwa tabel pengujian kami awalnya berisi lima baris dengan nilai yang ditunjukkan di bawah ini:
Kami sekarang mengatur tingkat isolasi untuk membaca berulang, memulai transaksi, dan menjalankan kueri penghitungan kami. Seperti yang Anda harapkan, hasilnya adalah lima . Tidak ada misteri besar sejauh ini.
Masih mengeksekusi di dalam transaksiterbaca berulang yang sama , kami menjalankan kueri penghitungan lagi, tetapi kali ini saat transaksi bersamaan kedua memasukkan baris baru ke dalam tabel yang sama. Diagram di bawah ini menunjukkan urutan kejadian, dengan transaksi kedua menambahkan baris dengan nilai 2 dan 6 (Anda mungkin telah memperhatikan bahwa nilai-nilai ini mencolok karena tidak adanya mereka tepat di atas):
Jika kueri penghitungan kami berjalan di dapat dibuat serial tingkat isolasi, itu akan dijamin untuk menghitung lima atau tujuh baris (lihat artikel sebelumnya dalam seri ini jika Anda membutuhkan penyegaran tentang mengapa demikian). Bagaimana cara berjalan di kurang terisolasi tingkat membaca berulang mempengaruhi banyak hal?
Nah, baca berulang isolasi menjamin bahwa menjalankan kueri penghitungan kedua akan melihat semua baris yang telah dibaca sebelumnya, dan mereka akan berada dalam status yang sama seperti sebelumnya. Tangkapannya adalah bahwa isolasi baca berulang mengatakan tidak ada tentang bagaimana transaksi harus memperlakukan baris baru (hantu).
Bayangkan transaksi penghitungan baris kami (T1 ) memiliki strategi eksekusi fisik di mana baris dicari dalam urutan indeks menaik. Ini adalah kasus umum, misalnya ketika pemindaian indeks b-tree yang dipesan-maju digunakan oleh mesin eksekusi. Sekarang, setelah transaksi T1 menghitung baris 1 dan 3 dalam urutan menaik, transaksi T2 mungkin menyelinap masuk, menyisipkan baris baru 2 dan 6, lalu melakukan transaksinya.
Meskipun kami terutama memikirkan perilaku logis pada saat ini, saya harus menyebutkan bahwa tidak ada dalam implementasi penguncian SQL Server dari pembacaan berulang untuk mencegah transaksi T2 dari melakukan ini. Kunci bersama diambil oleh transaksi T1 pada baris yang telah dibaca sebelumnya mencegah baris tersebut diubah, tetapi tidak mencegah baris baru agar tidak dimasukkan ke dalam rentang nilai yang diuji oleh kueri penghitungan kami (tidak seperti kunci rentang kunci dalam penguncian isolasi yang dapat diserialkan).
Bagaimanapun, dengan komitmen dua baris baru, transaksi T1 melanjutkan pencarian urutan menaik, akhirnya menemukan baris 4, 5, 6, dan 7. Perhatikan bahwa T1 melihat baris 6 baru dalam skenario ini, tetapi tidak baris baru 2 (karena pencarian berurutan, dan posisinya saat penyisipan terjadi).
Hasilnya adalah pembacaan berulang menghitung laporan kueri bahwa tabel berisi enam baris (nilai 1, 3, 4, 5, 6 dan 7). Hasil ini tidak konsisten dengan hasil sebelumnya dari lima baris diperoleh dalam transaksi yang sama . Pembacaan kedua menghitung phantom row 6 tetapi melewatkan phantom row 2. Begitu banyak makna intuitif dari pembacaan berulang!
Contoh Pembaruan Serentak
Situasi serupa dapat muncul dengan pembaruan concurrent bersamaan bukannya sisipan. Bayangkan tabel pengujian kami diatur ulang untuk memuat lima baris yang sama seperti sebelumnya:
Kali ini, kami hanya akan menjalankan kueri penghitungan sekali di pembacaan berulang tingkat isolasi, sementara transaksi serentak kedua memperbarui baris dengan nilai 5 menjadi nilai 2:
Transaksi T1 lagi mulai menghitung baris, (dalam urutan menaik) bertemu baris 1 dan 3 terlebih dahulu. Sekarang, transaksi T2 masuk, mengubah nilai baris 5 menjadi 2 dan melakukan:
Saya telah menunjukkan baris yang diperbarui di posisi yang sama seperti sebelumnya untuk memperjelas perubahan, tetapi indeks b-tree yang kami pindai mempertahankan data dalam urutan logis, sehingga gambaran sebenarnya lebih dekat dengan ini:
Intinya transaksi T1 secara bersamaan memindai struktur yang sama ini dalam urutan maju, saat ini diposisikan tepat setelah entri untuk nilai 3. Kueri penghitungan terus memindai ke depan dari titik itu, menemukan baris 4 dan 7 (tetapi tentu saja bukan baris 5).
Untuk meringkas, kueri penghitungan melihat baris 1, 3, 4, dan 7 dalam skenario ini. Ini melaporkan hitungan empat baris – yang aneh, karena tabel tampaknya berisi lima baris seluruh!
Menjalankan kueri penghitungan kedua dalam transaksi baca berulang yang sama akan melaporkan lima baris, untuk alasan yang sama seperti sebelumnya. Sebagai catatan terakhir, jika Anda bertanya-tanya, penghapusan bersamaan tidak memberikan peluang untuk anomali berbasis hantu di bawah isolasi baca berulang.
Pemikiran Terakhir
Contoh sebelumnya sama-sama menggunakan pemindaian urutan naik dari struktur indeks untuk menyajikan tampilan sederhana tentang jenis efek yang dapat dimiliki hantu pada repeatable-read pertanyaan. Penting untuk dipahami bahwa ilustrasi ini tidak bergantung pada arah pemindaian atau fakta bahwa indeks b-tree digunakan. Tolong jangan jangan membentuk pandangan bahwa pemindaian yang dipesan entah bagaimana bertanggung jawab dan karenanya harus dihindari!
Efek konkurensi yang sama dapat dilihat dengan pemindaian urutan menurun dari struktur indeks, atau dalam berbagai skenario akses data fisik lainnya. Intinya adalah bahwa fenomena hantu secara khusus diizinkan (meskipun tidak diperlukan) oleh standar SQL untuk transaksi pada tingkat isolasi baca yang berulang.
Tidak semua transaksi memerlukan jaminan isolasi lengkap yang disediakan oleh isolasi serial, dan tidak banyak sistem yang dapat mentolerir efek samping jika mereka melakukannya. Namun demikian, ada baiknya untuk memiliki pemahaman yang baik tentang jaminan yang diberikan oleh berbagai tingkat isolasi.
Lain kali
Bagian selanjutnya dalam seri ini melihat jaminan isolasi yang lebih lemah yang ditawarkan oleh tingkat isolasi default SQL Server, baca komitmen .
[ Lihat indeks untuk keseluruhan seri ]