Apakah NOLOCK selalu buruk?

34

Saya seorang Pengembang Laporan yang ingin membuat pertanyaan saya seefisien mungkin. Saya dulu bekerja dengan DBA yang memberi tahu saya - saya percaya karena saya selalu berurusan dengan laporan pada Server Produksi - untuk digunakan NOLOCKdalam setiap permintaan.

Sekarang, saya bekerja dengan DBA yang telah dilarang NOLOCKdalam keadaan apa pun - bahkan ketika laporan saya (karena kurangnya indeks pada beberapa tabel) menghentikan replikasi dan pembaruan sistem. Menurut saya, dalam hal ini, a NOLOCKakan menjadi hal yang baik.

Karena sebagian besar pelatihan SQL saya telah datang berbagai DBA dengan pendapat yang sangat berbeda, saya ingin menanyakan ini ke berbagai DBA.

DataGirl
sumber
1
Sisi lain dari diskusi ini: dba.stackexchange.com/q/2684/2660
Nick Chammas

Jawaban:

30

Jika laporan Anda memblokir pembaruan yang DBA Anda benar: Anda tidak boleh menggunakannya sama sekali NOLOCK. Kenyataan bahwa ada yang konflik merupakan indikasi yang jelas bahwa jika Anda akan menggunakan kotor membaca Anda akan mendapatkan laporan yang tidak benar.

Menurut pendapat saya, selalu ada alternatif yang lebih baik daripada NOLOCK:

  • Apakah tabel produksi Anda hanya berlaku dan tidak pernah dimodifikasi? Tandai basis data hanya baca!
  • Pindaian tabel menyebabkan konflik kunci? Indeks tabel dengan tepat, manfaatnya berlipat ganda.
  • Tidak dapat memodifikasi / tidak tahu cara mengindeks dengan tepat? Gunakan ISOLASI SNAPSHOT .
  • Tidak dapat mengubah aplikasi untuk menggunakan snapshot? Aktifkan snapshot yang sudah dibaca !
  • Anda telah mengukur dampak dari versi baris dan memiliki bukti yang memengaruhi kinerja? Anda tidak dapat mengindeks data? dan Anda setuju dengan laporan yang salah ? Maka paling tidak bantulah diri Anda sendiri dan gunakan SET TRANSACTION ISOLATION LEVEL, bukan petunjuk permintaan. Akan lebih mudah untuk memperbaiki tingkat isolasi daripada memodifikasi setiap permintaan.
Remus Rusanu
sumber
6
Hati-hati: mengaktifkan snapshot yang sudah dibaca dapat merusak beberapa kode.
AK
33

Itu tidak selalu buruk.

Tentu saja itu memungkinkan Anda untuk membaca nilai-nilai yang tidak dikomit (yang dapat dibatalkan dan karenanya tidak pernah ada secara logis) serta memungkinkan fenomena seperti membaca nilai beberapa kali atau tidak sama sekali.

Satu-satunya tingkat isolasi yang menjamin bahwa Anda tidak akan menemui anomali seperti itu adalah serializable / snapshot. Di bawah nilai baca yang berulang dapat terlewatkan jika suatu baris dipindahkan (karena pembaruan kunci) sebelum pemindaian mencapai baris ini, nilai yang dibaca yang dibaca dapat dibaca dua kali jika pembaruan kunci menyebabkan baris yang telah dibaca sebelumnya bergerak maju.

Namun masalah ini lebih cenderung muncul nolockkarena, secara default, pada tingkat isolasi ini akan menggunakan pemindaian alokasi yang dialokasikan ketika memperkirakan ada lebih dari 64 halaman yang akan dibaca . Selain kategori masalah yang muncul saat baris berpindah antar halaman karena pembaruan kunci indeks, pemindaian alokasi yang dipesan ini juga rentan terhadap masalah dengan pemisahan halaman (di mana baris dapat dilewatkan jika halaman yang baru dialokasikan lebih awal dalam file daripada titiknya) sudah dipindai atau dibaca dua kali jika halaman yang sudah dipindai dibagi ke halaman selanjutnya dalam file).

Setidaknya untuk kueri sederhana (tabel tunggal) dimungkinkan untuk mencegah penggunaan pemindaian ini dan mendapatkan pemindaian kunci nolockdengan hanya dengan menambahkan sebuah ORDER BY index_keyke kueri sehingga Orderedproperti dari IndexScanis true.

Tetapi jika aplikasi pelaporan Anda tidak membutuhkan angka yang benar-benar tepat dan dapat mentolerir probabilitas yang lebih besar dari ketidakkonsistenan seperti itu mungkin dapat diterima.

Tapi tentu saja Anda tidak harus membuangnya di semua pertanyaan dengan harapan itu adalah tombol "turbo" ajaib. Serta kemungkinan yang lebih besar untuk menemukan hasil yang tidak normal pada tingkat isolasi atau tidak ada hasil sama sekali (kesalahan "Tidak dapat melanjutkan pemindaian dengan NOLOCK karena pergerakan data") bahkan ada kasus di mana kinerja dengan nolock dapat jauh lebih buruk .

Martin Smith
sumber
3
+1 - Kami sering menggunakannya karena tabel produksi kami tidak pernah dimodifikasi.
JNK
@ JNK Apa maksudmu dengan tidak pernah dimodifikasi?
Kuberchaun
4
Martin, saya akan menyarankan kata-kata yang sedikit berbeda: "nilai-nilai yang sudah dibaca dapat dibaca dan dibaca lebih dari satu kali". Kami dapat meminta agar baris diambil lebih dari dua kali dalam beberapa kasus eksotis.
AK
@ StarShip3000 Data yang kami gunakan untuk produksi pada dasarnya hanya-baca untuk pengguna akhir, sehingga sebagian besar pandangan mereka memiliki petunjuk NOLOCK
JNK
11

Apakah pelanggan Anda mentolerir hasil yang tidak konsisten dalam laporan? Jika jawabannya tidak, Anda tidak boleh menggunakan NOLOCK - Anda bisa mendapatkan hasil yang salah di bawah konkurensi. Saya menulis beberapa contoh di sini , di sini , dan di sini . Contoh-contoh ini menunjukkan output yang tidak konsisten di bawah READ COMMITTED dan REPEATABLE READ, tetapi Anda dapat mengubah mereka dan mendapatkan hasil yang salah dengan NOLOCK juga.

AK
sumber
Sebagian besar laporan yang saya buat tidak berjalan pada data saat ini. Sebagian besar pelanggan menjalankan laporan adalah data kemarin. Apakah jawaban Anda akan berubah jika itu masalahnya?
DataGirl
8

Sebagian besar laporan yang saya buat tidak berjalan pada data saat ini. Sebagian besar pelanggan menjalankan laporan adalah data kemarin. Apakah jawaban Anda akan berubah jika itu masalahnya?

Jika itu masalahnya, maka Anda memiliki satu opsi lagi yang mungkin:
Alih-alih menjalankan kueri Anda pada basis data produksi dan mengacaukan dengan kunci dan NOLOCK, Anda dapat menjalankan laporan Anda dari salinan basis data produksi.

Anda dapat mengaturnya sehingga secara otomatis dikembalikan dari cadangan setiap malam .
Tampaknya laporan Anda berjalan di server di situs pelanggan, jadi saya tidak tahu apakah pengaturan ini akan menjadi solusi yang tepat untuk Anda.
(tapi sekali lagi ... mereka seharusnya memiliki cadangan, jadi yang Anda butuhkan hanyalah ruang server untuk memulihkannya)

Saya seorang pengembang in-house, jadi ini lebih mudah bagi saya karena saya memiliki kontrol penuh atas server dan database.

Anda dapat melakukan ini setidaknya untuk laporan yang hanya membutuhkan data dari kemarin dan yang lebih lama. Mungkin beberapa laporan harus tetap ada di basis data produksi, tetapi setidaknya Anda memindahkan sebagian beban ke basis data lain (atau bahkan lebih baik, server lain).

Saya memiliki situasi yang sama di tempat kerja juga:
Kami menggunakan salinan basis data produksi seperti ini untuk hampir semua hal pelaporan, tetapi ada beberapa pertanyaan yang memerlukan data hari ini.

Christian Specht
sumber
Saya suka jawaban Anda dan itu akan berhasil - jika saya memiliki kontrol penuh - yang tidak saya lakukan. Sering kali, saya tidak memiliki kontrol penuh dan saya tidak dapat membuat indeks. Saya beruntung jika saya dapat menjalankan / menampilkan rencana Eksekusi.
DataGirl