Mengapa menggunakan tingkat isolasi BACA YANG TIDAK DICATAT?

225

Dalam bahasa Inggris yang sederhana, apa kerugian dan kelebihan menggunakan

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

dalam permintaan untuk aplikasi .NET dan aplikasi layanan pelaporan?

Kip Real
sumber

Jawaban:

210

Tingkat isolasi ini memungkinkan pembacaan yang kotor. Satu transaksi dapat melihat perubahan yang tidak dikomit dilakukan oleh beberapa transaksi lainnya.

Untuk mempertahankan tingkat isolasi tertinggi, DBMS biasanya memperoleh kunci pada data, yang dapat mengakibatkan hilangnya konkurensi dan overhead penguncian yang tinggi. Level isolasi ini merilekskan properti ini.

Anda mungkin ingin membaca artikel WikipediaREAD UNCOMMITTED untuk beberapa contoh dan bacaan lebih lanjut.


Anda juga mungkin tertarik untuk memeriksa artikel blog Jeff Atwood tentang bagaimana ia dan timnya mengatasi masalah kebuntuan di masa-masa awal Stack Overflow. Menurut Jeff:

Tetapi apakah nolockberbahaya? Bisakah Anda akhirnya membaca data yang tidak valid dengan read uncommittedpada? Ya, secara teori. Anda tidak akan menemukan kekurangan astronot arsitektur database yang mulai menjatuhkan sains ACID pada Anda dan semua tetapi menarik alarm kebakaran gedung ketika Anda memberi tahu mereka bahwa Anda ingin mencoba nolock. Memang benar: teorinya menakutkan. Tetapi inilah yang saya pikirkan: "Secara teori tidak ada perbedaan antara teori dan praktik. Dalam praktik ada."

Saya tidak akan merekomendasikan menggunakan nolock sebagai umum "baik untuk apa yang Anda sakit" memperbaiki minyak ular untuk masalah kebuntuan database yang mungkin Anda miliki. Anda harus mencoba mendiagnosis sumber masalahnya terlebih dahulu.

Namun dalam praktiknya menambah nolockpertanyaan yang benar-benar Anda ketahui sederhana, urusan hanya-baca tampaknya tidak pernah menimbulkan masalah ... Selama Anda tahu apa yang Anda lakukan.

Satu alternatif ke READ UNCOMMITTEDlevel yang mungkin ingin Anda pertimbangkan adalah READ COMMITTED SNAPSHOT. Mengutip Jeff lagi:

Snapshots mengandalkan metode pelacakan perubahan data yang sama sekali baru ... lebih dari sekadar perubahan logis, itu memerlukan server untuk menangani data secara fisik berbeda. Setelah metode pelacakan perubahan data baru ini diaktifkan, metode ini akan membuat salinan, atau potret setiap perubahan data. Dengan membaca snapshot ini alih-alih data langsung pada saat pertikaian, Shared Locks tidak diperlukan lagi pada pembacaan, dan kinerja keseluruhan basis data dapat meningkat.

Daniel Vassallo
sumber
13
Penulis tampaknya menyiratkan bahwa read uncommitted / no lock akan mengembalikan data apa pun yang terakhir kali dilakukan. Pemahaman saya dibaca tanpa komitmen akan mengembalikan nilai apa pun yang ditetapkan terakhir bahkan dari transaksi yang tidak terikat. Jika demikian, hasilnya tidak akan mengambil data "beberapa detik kedaluwarsa". Itu akan (atau setidaknya bisa jika transaksi yang menulis data yang Anda baca dibatalkan) menjadi mengambil data yang tidak ada atau tidak pernah dilakukan. Apakah saya salah?
xr280xr
4
Jawaban yang bagus BTW, Oracle memiliki "snapshot" secara default sejak saya mengetahuinya, mungkin beberapa dekade sebelum Sql Server memperkenalkannya. Saya cukup kecewa ketika memulai dengan SQL Server dan saya menemukan bahwa semua masalah konkurensi diselesaikan dengan menggunakan mekanisme penguncian "primitif". Tidak pernah melihat "Baca tanpa komitmen" di Oracle. Dan praktisi itu sama berbahayanya dengan para astronot.
Stefan Steinegger
13
READ UNCOMMITTEDjuga dapat menyebabkan Anda membaca baris dua kali, atau melewatkan seluruh baris . Jika pemisahan halaman terjadi saat Anda membaca, maka Anda dapat kehilangan seluruh data. WITH(NOLOCK)seharusnya hanya digunakan jika keakuratan hasil tidak penting
Ian Boyd
8
@DanielNolan, Merekomendasikan artikel itu berbahaya karena Jeff tidak tahu apa yang dia lakukan . Read-uncommmited hanya masuk akal untuk membaca data tidak akan pernah dimodifikasi. Mencoba menggunakannya untuk membaca tabel yang akan ditulis berarti Anda akan membaca sesuatu yang akan dibatalkan. Bukan hanya Anda membaca data yang berumur beberapa detik, tetapi Anda juga ...................................... ................... ‌ ‌ ........................... ....
Pacerier
5
................................... membaca data yang bahkan tidak pernah dikomit. Itulah definisi dari bacaan yang rusak. Dan jika Anda akan menulis berdasarkan hasil dari bacaan yang tidak dikomit itu, pada praktiknya Anda akan menulis data yang rusak. Juga artikel itu menyatakan bahwa "MySQL, yang tumbuh di aplikasi web, jauh lebih pesimis di luar kotak daripada SQL Server". Tidak benar, Sql Server bekerja pada tingkat read-commited secara default, sementara MySQL bekerja pada read- reads secara default, lima level dari read-uncommitted.
Pacerier
36

Ini bisa berguna untuk melihat perkembangan permintaan memasukkan panjang, membuat perkiraan kasar (suka COUNT(*)atau kasar SUM(*)) dll.

Dengan kata lain, hasil kueri baca kotor kembali baik-baik saja selama Anda memperlakukannya sebagai perkiraan dan tidak membuat keputusan penting berdasarkan pada mereka.

Quassnoi
sumber
36

Kasus penggunaan favorit saya read uncommitedadalah untuk men-debug sesuatu yang terjadi di dalam suatu transaksi.

Mulai perangkat lunak Anda di bawah debugger, saat Anda melangkah melalui baris kode, itu membuka transaksi dan memodifikasi database Anda. Ketika kode dihentikan, Anda bisa membuka penganalisis kueri, mengatur tingkat isolasi tidak dibaca yang sudah dibaca dan membuat pertanyaan untuk melihat apa yang sedang terjadi.

Anda juga dapat menggunakannya untuk melihat apakah prosedur yang berjalan lama macet atau memperbarui database Anda dengan benar.

Sangat bagus jika perusahaan Anda suka membuat prosedur tersimpan yang terlalu rumit.

neves
sumber
6
Perusahaan saya suka membuat prosedur tersimpan yang terlalu rumit. Ide yang bagus untuk pemecahan masalah!
Brandon
22

Keuntungannya adalah bisa lebih cepat dalam beberapa situasi. Kerugiannya adalah hasilnya bisa salah (data yang belum berkomitmen dapat dikembalikan) dan tidak ada jaminan bahwa hasilnya dapat diulang.

Jika Anda peduli tentang akurasi, jangan gunakan ini.

Informasi lebih lanjut tentang MSDN :

Menerapkan pembacaan kotor, atau penguncian level 0 isolasi, yang berarti bahwa tidak ada kunci bersama yang dikeluarkan dan tidak ada kunci eksklusif yang dihormati. Ketika opsi ini diatur, dimungkinkan untuk membaca data yang tidak berkomitmen atau kotor; nilai dalam data dapat diubah dan baris dapat muncul atau menghilang dalam kumpulan data sebelum akhir transaksi. Opsi ini memiliki efek yang sama dengan menetapkan NOLOCK pada semua tabel di semua pernyataan SELECT dalam suatu transaksi. Ini adalah yang paling tidak membatasi dari empat level isolasi.

Mark Byers
sumber
Bagaimana ini akan memengaruhi kecepatan kueri?
Kip Real
11
@Kip - selectpernyataan tidak perlu menunggu untuk mendapatkan kunci bersama pada sumber daya yang dikunci secara eksklusif oleh transaksi lainnya.
Jarrod Dixon
15

Kapan boleh digunakan READ UNCOMMITTED?

Aturan praktis

Bagus : Laporan agregat besar menunjukkan total yang terus berubah.

Beresiko : Hampir semuanya.

Berita baiknya adalah bahwa sebagian besar laporan hanya baca termasuk dalam kategori Baik .

Lebih detail...

Ok untuk menggunakannya:

  • Hampir semua laporan agregat yang dihadapi pengguna untuk data saat ini, non-statis, misalnya Tahun hingga tanggal penjualan. Risiko margin kesalahan (mungkin <0,1%) yang jauh lebih rendah daripada faktor ketidakpastian lainnya seperti memasukkan kesalahan atau hanya keacakan ketika data secara tepat direkam dari menit ke menit.

Itu mungkin mencakup sebagian besar dari apa yang akan dilakukan departemen Business Intelligence, katakanlah, SSR. Pengecualian tentu saja, adalah sesuatu dengan tanda $ di depannya. Banyak orang menghitung uang dengan lebih banyak semangat daripada diterapkan pada metrik inti terkait yang diperlukan untuk melayani pelanggan dan menghasilkan uang itu. (Saya menyalahkan akuntan).

Saat berisiko

  • Laporan apa pun yang turun ke tingkat detail. Jika detail itu diperlukan, biasanya itu menyiratkan bahwa setiap baris akan relevan dengan keputusan. Bahkan, jika Anda tidak dapat menarik subset kecil tanpa memblokir mungkin karena alasan yang baik sedang diedit.

  • Data historis. Ini jarang membuat perbedaan praktis tetapi sementara pengguna memahami terus-menerus mengubah data tidak bisa sempurna, mereka tidak merasakan hal yang sama tentang data statis. Bacaan kotor tidak akan menyakitkan di sini, tetapi bacaan ganda terkadang dapat terjadi. Karena Anda seharusnya tidak memiliki blok pada data statis, mengapa mengambil risiko?

  • Hampir semua yang memberi makan aplikasi yang juga memiliki kemampuan menulis.

Ketika bahkan skenario OK tidak OK.

  • Apakah ada aplikasi atau proses pembaruan yang memanfaatkan transaksi besar tunggal? Yang menghapus kemudian masukkan kembali banyak catatan yang Anda laporkan? Dalam hal ini Anda benar-benar tidak dapat menggunakan NOLOCKtabel tersebut untuk apa pun.
Adamantish
sumber
Poin bagus tentang laporan. Sebenarnya ide pertama yang muncul di benak saya adalah jika saya harus menggunakan read uncommitteduntuk aplikasi web ketika pengguna melihat beberapa kotak UI di mana akurasi data tidak begitu penting. Pengguna hanya ingin ikhtisar cepat catatan apa yang mungkin ada di sana, dan mungkin dengan beberapa paging, pengurutan & penyaringan. Hanya ketika pengguna mengklik tombol Edit, maka saya mencoba membaca catatan terbaru dengan tingkat isolasi yang lebih ketat. Tidakkah pendekatan seperti itu lebih baik dalam hal kinerja?
JustAMartin
Ya, saya pikir itu masuk akal. Ingat bahwa masalah yang lebih penting adalah memastikan bahwa data belum diubah oleh orang lain antara waktu menekan tombol edit dan waktu pengiriman. Anda bisa mengatasinya dengan memulai transaksi seperti mengambil data select item from things with (UPDLOCK). Letakkan batas waktu cepat di sana sehingga jika tidak dapat memperoleh kunci dengan cepat itu memberi tahu pengguna itu sedang diedit. Itu akan membuat Anda aman tidak hanya dari pengguna tetapi juga pengembang. Satu-satunya masalah di sini adalah Anda harus mulai memikirkan batas waktu dan bagaimana Anda mengatasinya di UI.
Adamantish
6

Mengenai pelaporan, kami menggunakannya pada semua kueri pelaporan kami untuk mencegah kueri merobohkan basis data. Kita dapat melakukan itu karena kita menarik data historis, bukan data yang terkini.

Hugh Seagraves
sumber
4

Gunakan READ_UNCOMMITTED dalam situasi di mana sumber sangat tidak mungkin berubah.

  • Saat membaca data historis. mis. beberapa log penempatan yang terjadi dua hari lalu.
  • Saat membaca metadata lagi. mis. aplikasi berbasis metadata.

Jangan gunakan READ_UNCOMMITTED ketika Anda tahu bahwa sumber daya dapat berubah selama operasi pengambilan.

neo
sumber
1
Saya merasa sebaliknya berlaku. Data statis pertama harus dibaca dengan baik tanpa blok. Jika tidak memblokir maka Anda sekarang telah menemukan ada masalah transaksi gantung penting untuk diperbaiki. Juga pengguna akan mengharapkan ini untuk mencocokkan ke tempat desimal terakhir apa pun yang mereka cetak untuk laporan tahunan tahun lalu. Mereka umumnya tidak mengharapkan laporan yang sama yang mereka tahu terus berubah. Ini tidak berlaku untuk pelaporan terperinci, sangat sensitif terhadap waktu atau keuangan tetapi jika 1 kesalahan memasukkan 1000 dapat ditoleransi maka demikian juga READ UNCOMMITTED.
Adamantish
TLDR: Jika data tidak akan berubah, Anda tidak perlu BACA TIDAK DISESUAIKAN karena bagaimanapun juga tidak ada blok. Jika Anda salah dan itu berubah maka ada baiknya Anda memblokir pengguna agar tidak mendapatkan data yang lebih kotor dari yang diharapkan.
Adamantish
Ya, saya cenderung setuju dengan @Adamantish di sini - Anda bisa mendapat manfaat dari READ UNCOMMITTEDsebagian besar situasi ketika data Anda sedang digunakan secara aktif dan Anda ingin mengurangi beban di server untuk menghindari kemungkinan deadlock dan rollback transaksi hanya karena beberapa pengguna yang dengan sembrono menyalahgunakan " Perbarui tombol di halaman web dengan datagrid. Pengguna yang melihat banyak catatan pada saat yang sama, biasanya tidak terlalu peduli jika data sedikit usang atau sebagian diperbarui. Hanya ketika pengguna akan mengedit catatan, maka Anda mungkin ingin memberinya data yang paling akurat.
JustAMartin
2

Ini akan memberi Anda bacaan kotor, dan menunjukkan kepada Anda transaksi yang belum dilakukan. Itu jawaban yang paling jelas. Saya tidak berpikir itu ide yang baik untuk menggunakan ini hanya untuk mempercepat bacaan Anda. Ada cara lain untuk melakukan itu jika Anda menggunakan desain basis data yang baik.

Juga menarik untuk dicatat apa yang tidak terjadi. BACA UNCOMMITTED tidak hanya mengabaikan kunci meja lainnya. Ini juga tidak menyebabkan kunci apa pun.

Pertimbangkan Anda membuat laporan besar, atau Anda memigrasikan data dari database Anda menggunakan pernyataan SELECT yang besar dan mungkin rumit. Ini akan menyebabkan kunci bersama yang dapat ditingkatkan menjadi kunci tabel bersama selama durasi transaksi Anda. Transaksi lain mungkin membaca dari tabel, tetapi pembaruan tidak mungkin. Ini mungkin ide yang buruk jika ini merupakan basis data produksi karena produksi mungkin berhenti sepenuhnya.

Jika Anda menggunakan READ UNCOMMITTED, Anda tidak akan menetapkan kunci bersama di atas meja. Anda dapat memperoleh hasil dari beberapa transaksi baru atau Anda mungkin tidak bergantung pada tabel data yang dimasukkan dan berapa lama transaksi SELECT Anda baca. Anda juga dapat memperoleh data yang sama dua kali jika misalnya terjadi perpecahan halaman (data akan disalin ke lokasi lain dalam file data).

Jadi, jika sangat penting bagi Anda agar data dapat disisipkan saat melakukan SELECT Anda, BACA TIDAK DIKETAHUI mungkin masuk akal. Anda harus mempertimbangkan bahwa laporan Anda mungkin mengandung beberapa kesalahan, tetapi jika didasarkan pada jutaan baris dan hanya beberapa dari mereka yang diperbarui saat memilih hasilnya, ini mungkin "cukup baik". Transaksi Anda juga dapat gagal semuanya karena keunikan baris mungkin tidak dijamin.

Cara yang lebih baik sama sekali adalah dengan menggunakan SNAPSHOT ISOLATION LEVEL tetapi aplikasi Anda mungkin perlu beberapa penyesuaian untuk menggunakan ini. Salah satu contohnya adalah jika aplikasi Anda mengambil kunci eksklusif pada satu baris untuk mencegah orang lain membacanya dan masuk ke mode edit di UI. SNAPSHOT ISOLATION LEVEL juga datang dengan penalti performa yang cukup besar (terutama pada disk). Tapi Anda bisa mengatasinya dengan melemparkan perangkat keras pada masalah. :)

Anda juga dapat mempertimbangkan memulihkan cadangan database untuk digunakan untuk melaporkan atau memuat data ke dalam gudang data.

Olle Johansson
sumber
0

Ini dapat digunakan untuk tabel sederhana, misalnya dalam tabel audit hanya sisipkan, di mana tidak ada pembaruan untuk baris yang ada, dan tidak ada fk ke tabel lain. Sisipan adalah sisipan sederhana, yang tidak memiliki atau sedikit kemungkinan rollback.

Sofian
sumber
-7

Saya selalu menggunakan READ UNCOMMITTED sekarang. Cepat dengan masalah yang paling sedikit. Saat menggunakan isolasi lain, Anda hampir selalu menemukan beberapa masalah Pemblokiran.

Selama Anda menggunakan bidang Peningkatan Otomatis dan memberikan sedikit lebih banyak perhatian untuk memasukkan maka Anda baik-baik saja, dan Anda bisa mengucapkan selamat tinggal pada masalah memblokir.

Anda dapat membuat kesalahan dengan READ UNCOMMITED tetapi sejujurnya, sangat mudah memastikan sisipan Anda adalah bukti penuh. Sisipan / Pembaruan yang menggunakan hasil dari pemilihan adalah satu-satunya hal yang perlu Anda perhatikan. (Gunakan BACA BERKOMITMEN di sini, atau pastikan pembacaan yang kotor tidak akan menyebabkan masalah)

Jadi, baca Dirty Reads (Khusus untuk laporan besar), perangkat lunak Anda akan berjalan lebih lancar ...

Clive
sumber
6
Ini sangat tidak akurat dan hanya menyentuh permukaan masalah yang dapat terjadi dengan nolock. Halaman dapat dipisah, bergabung bisa gagal, Anda bisa membaca data yang tidak ada atau menggandakan data. Tidak ada cara untuk membuatnya sangat mudah: Anda tidak dapat mempercayai keakuratan apa pun di bawah tingkat isolasi ini. BACA SNAPSHOT BERKOMITMEN adalah "obat mujarab palsu" yang kurang berbahaya
Mark Sowul
@MarkSowul Pengunduran diri dari jawaban ini sepertinya tidak adil bagi saya. @Clive jelas bahwa ia akan beralih ke Committeduntuk memasukkan dan memperbarui. Adapun masalah lain ia juga menunjukkan kesadaran tentang masalah pemisah halaman dalam menyebutkan menggunakan kunci penambahan otomatis. Saya setuju dengannya bahwa hampir semua pelaporan langsung yang dibuat hanya untuk dibaca oleh manusia dapat menoleransi sedikit perbedaan di tempat desimal terakhir. Saya setuju ini cerita yang berbeda untuk daftar detail atau data yang ditakdirkan untuk dibaca dan diubah oleh mesin dan begitu pula Clive.
Adamantish
1
Komentar ini juga menunjukkan kurangnya pemahaman penuh tentang kemungkinan masalah yang datang dengan nolock. "Sedikit perbedaan di tempat desimal terakhir" hampir tidak mencakupnya. Bahkan menyentuh "hanya gunakan baca yang dilakukan untuk memasukkan / memperbarui" salah sebagai saran umum (bagaimana jika itu "memasukkan catatan jika tidak ada"?). Dalam hal apa pun, "[baca tanpa komitmen] cepat dengan masalah yang paling sedikit" adalah pasti salah.
Mark Sowul
Sebagai catatan, saya setuju dengan jawaban Anda, Adamantish: agregasi kira-kira akurat dan sedikit lainnya.
Mark Sowul