Cara mereproduksi “Tidak dapat melanjutkan memindai dengan NOLOCK karena pergerakan data”

10

Saya kadang-kadang mendapatkan "Tidak dapat melanjutkan pemindaian NOLOCKkarena pergerakan data" dengan beberapa pekerjaan besar, yang ada WITH (NOLOCK)pada kueri pemilihan.

Saya mengerti ini ada hubungannya dengan upaya memilih data ketika telah terjadi pemisahan halaman yang menyebabkan data tidak lagi berada di tempat yang seharusnya - saya berasumsi bahwa itulah yang terjadi di lingkungan saya.

Bagaimana saya mereproduksi ini?

Saya mencoba melakukan solusi jangka pendek untuk menangkap kesalahan dan coba lagi ketika ini terjadi, tetapi saya tidak bisa mengujinya jika saya tidak bisa memperbanyaknya. Apakah ada cara yang cukup dapat diandalkan untuk menyebabkan ini?

Ketika itu benar-benar terjadi, mengeksekusi kueri kembali menghasilkan kesuksesan - jadi saya tidak benar-benar khawatir tentang data aktual atau database yang rusak secara permanen. Beberapa tabel dalam kueri (beserta indeksnya) sering dijatuhkan, diciptakan kembali, dan dihuni kembali berulang kali, jadi saya berasumsi itu terkait dengan hal itu.

Menghapus NOLOCKadalah masalah jangka panjang saya untuk ditangani. Alasannya NOLOCKdiletakkan di sana di tempat pertama adalah bahwa pertanyaannya sangat buruk sehingga mereka menemui jalan buntu dengan transaksi sehari-hari, jadi NOLOCKadalah bantuan band untuk menghentikan kebuntuan (yang bekerja). Jadi saya memerlukan bantuan band pada bantuan band sampai kita dapat melakukan solusi permanen.

Jika saya bisa mereproduksinya dengan Hello World, saya akan berencana untuk mungkin menampar bantuan band ke dalam pekerjaan dalam waktu kurang dari satu jam. Tidak dapat melakukan pencarian-dan-ganti menghapus NOLOCK, karena saya akan mulai mendapatkan kebuntuan aplikasi lagi, yang lebih buruk bagi saya daripada pekerjaan yang gagal sesekali.

Menggunakan isolasi snapshot yang sudah dibaca adalah kemungkinan yang baik - saya harus bekerja dengan tim database kami untuk mendapatkan detail lebih lanjut tentang itu. Bagian dari masalah kami adalah bahwa kami tidak memiliki ahli SQL Server untuk menangani hal semacam itu, dan saya tidak mengerti tingkat isolasi dengan cukup baik untuk membuat perubahan itu sekarang.

wookie23
sumber
1
Sudahkah Anda mempertimbangkan untuk sekadar keluar NOLOCKdari pekerjaan ini? 601 seharusnya menjadi kekhawatiran Anda yang paling kecil jika hasil dari pertanyaan ini seharusnya akurat . Paul White menunjukkan contoh yang sangat buruk dari membaca data yang seharusnya tidak mungkin dilakukan di sini .
Aaron Bertrand
3
Anda bisa mengatur DEADLOCK_PRIORITYke LOWdalam pekerjaan, sehingga jika ada deadlock, pekerjaan akan gagal, dan bukan aplikasi. Setelah itu, Anda bisa meneliti kebuntuan dan mencari tahu mengapa itu terjadi, dan memperbaiki masalah itu. Ini bisa menjadi perbaikan yang sangat sederhana, seperti menukar urutan dua pernyataan. Apapun masalahnya, NOLOCKadalah bukan solusi , sehingga berhenti berusaha untuk memaksa hal itu terjadi hanya karena itulah yang paling mudah.
Aaron Bertrand
@AaronBertrand Terima kasih, tidak tahu tentang DEADLOCK_PRIORITY - Saya akan memeriksanya. Kami mencoba melacak kebuntuan, tetapi itu terjadi di berbagai waktu yang tampaknya acak, dan hanya sekali atau dua kali per hari, dan tidak pernah dapat diproduksi kembali berdasarkan permintaan - pekerjaan terjadwal kami menjalankan puluhan ribu kueri setiap jam, dan aplikasi kami mengeksekusi ratusan kueri setiap kali memuat halaman atau menyimpan sesuatu, dan kami belum melacak kueri mana di kedua sisi yang terlibat dalam kebuntuan. Saya tidak berniat meninggalkan NOLOCK di sana selamanya, itulah sebabnya kami mencari solusi jangka panjang yang lebih baik.
wookie23
1
Anda menyebutkan bahwa Anda mengalami kesulitan melacak kebuntuan. Mengingat bahwa Anda berada di 2008 R2, Anda mungkin melihat di sini: sqlservercentral.com/articles/deadlock/65658 Jonathan Kehayias lebih memilih untuk mengambil informasi kebuntuan dari buffer cincin.
Kenneth Fisher
Jawaban dan komentar mengatasi masalah mendasar dengan baik, tetapi apakah Anda masih tertarik untuk menemukan cara untuk mereproduksi ini sebagai latihan intelektual?
James L

Jawaban:

8

Karena satu 'bantuan band' potensial untuk masalah NOLOCK adalah berhenti menggunakan NOLOCK dan mulai menggunakan isolasi READ_COMMITTED_SNAPSHOT, saya ingin mengarahkan Anda ke posting blog di http://www.brentozar.com oleh Kendra Little: Menerapkan Snapshot atau Baca Komitmen Snapshot Isolasi di SQL Server: A Guide .

Kendra memberikan cukup banyak detail tentang manfaat dan risiko dengan menggunakan tingkat isolasi READ_COMMITTED_SNAPSHOT.

  1. Level isolasi ini menjadi level isolasi standar untuk kode database.
  2. Anda harus memiliki hanya satu pengguna dalam database untuk membuat perubahan ke tingkat isolasi READ_COMMITTED_SNAPSHOT.
  3. Bahkan jika Anda menggunakan isolasi READ_COMMITTED_SNAPSHOT Anda masih harus menghapus petunjuk NOLOCK karena mereka menimpa default.
  4. Beberapa kode Anda mungkin memiliki masalah yang perlu disembuhkan.

Beberapa tahun yang lalu kami menerapkan isolasi READ_COMMITTED_SNAPSHOT pada database yang sangat menderita karena pemblokiran . Tetapi begitu kami mengubah tingkat isolasi, kami mulai mendapatkan kebuntuan di beberapa area kritis.

Kenapa ini terjadi? Karena tingkat isolasi sebelumnya menyebabkan pemblokiran berat, kode itu bisa "tidak pernah" mencapai titik kebuntuan. Namun, dengan isolasi READ_COMMITTED_SNAPSHOT, kueri dapat terus bergerak maju. Namun, beberapa persentase dari transaksi menunggu tidak lagi mulai menemui jalan buntu.

Untungnya kasus kami diselesaikan dengan cepat dengan menentukan titik kebuntuan dan menyesuaikan indeks pada beberapa tabel untuk memiliki urutan kolom yang lebih rasional. Ini sangat mengurangi masalah penguncian kami.

RLF
sumber