Apa itu "dengan (nolock)" di SQL Server?


610

Dapatkah seseorang menjelaskan implikasi penggunaan with (nolock)pada permintaan, ketika Anda seharusnya / tidak seharusnya menggunakannya?

Misalnya, jika Anda memiliki aplikasi perbankan dengan tingkat transaksi tinggi dan banyak data dalam tabel tertentu, dalam jenis pertanyaan apa saja nolock boleh? Apakah ada kasus ketika Anda harus selalu menggunakannya / tidak pernah menggunakannya?



1
satu tautan di sini - mssqltips.com/sqlservertip/2470/…
Steam

1
Berikut ini adalah ringkasan yang bagus tentang implikasi menggunakan NOLOCK blogs.msdn.com/b/davidlean/archive/2009/04/06/...
Bryan

Jawaban:


461

WITH (NOLOCK) adalah setara dengan menggunakan READ UNCOMMITED sebagai tingkat isolasi transaksi. Jadi, Anda berisiko membaca baris yang tidak berkomitmen yang kemudian dibatalkan, yaitu data yang tidak pernah berhasil masuk ke dalam basis data. Jadi, sementara itu dapat mencegah pembacaan jalan buntu oleh operasi lain, ia datang dengan risiko. Dalam aplikasi perbankan dengan tingkat transaksi tinggi, itu mungkin tidak akan menjadi solusi yang tepat untuk masalah apa pun yang Anda coba selesaikan dengan IMHO.


156
Sebagian besar aplikasi perbankan dapat menggunakan nolock dengan aman karena bersifat transaksional dalam pengertian bisnis. Anda hanya menulis baris baru, Anda tidak pernah memperbaruinya.
Jonathan Allen

49
@ Grauenwolf- Baris yang disisipkan tetapi tidak dikomit masih dapat menyebabkan pembacaan yang kotor.
saasman

16
@ Saasman- Jika Anda tidak pernah melakukan transaksi balik, itu tidak masalah. Dan dengan tabel insert-only, kemungkinan rollback sangat tipis. Dan jika itu terjadi, Anda masih akan memperbaikinya di akhir laporan varians hari.
Jonathan Allen

1
Saya bercokol. Saya menganggap Ditambahkan tanpa kunci petunjuk. Sebagai contoh:
Ross Bush

11
Jika Anda menggunakan NOLOCKdengan SELECTAnda menjalankan risiko mengembalikan baris yang sama lebih dari sekali (data duplikat) jika data pernah dimasukkan (atau diperbarui) ke dalam tabel saat melakukan pemilihan.
Ian Boyd

170

Pertanyaannya adalah apa yang lebih buruk:

  • jalan buntu, atau
  • nilai yang salah?

Untuk database keuangan, kebuntuan jauh lebih buruk daripada nilai yang salah. Saya tahu itu terdengar mundur, tetapi dengarkan saya. Contoh tradisional dari transaksi DB adalah Anda memperbarui dua baris, mengurangkan dari satu dan menambahkan ke yang lain. Itu salah.

Dalam database keuangan Anda menggunakan transaksi bisnis. Itu berarti menambahkan satu baris ke setiap akun. Sangat penting bahwa transaksi ini selesai dan baris-barisnya ditulis dengan sukses.

Mendapatkan saldo akun untuk sementara salah bukanlah masalah besar, untuk itulah rekonsiliasi akhir hari itu. Dan cerukan dari rekening jauh lebih mungkin terjadi karena dua ATM digunakan sekaligus daripada karena pembacaan tidak berkomitmen dari database.

Yang mengatakan, SQL Server 2005 memperbaiki sebagian besar bug yang NOLOCKdiperlukan. Jadi kecuali Anda menggunakan SQL Server 2000 atau yang lebih lama, Anda seharusnya tidak membutuhkannya.

Bacaan Lebih Lanjut
Versi-Tingkat Baris


22
Mendapatkan saldo akun sementara salah bukan masalah besar? Bagaimana jika transaksi itu adalah transaksi di mana Anda mengambil uang tunai dari atm tanpa batas cerukan?
Belajar

13
@Pelajaran: Apa yang terjadi jika Anda mengeluarkan uang 30 detik sebelum seseorang menagih kartu Anda? Sampai semua komunikasi bersifat turly, cerukan akan menjadi kenyataan hidup.
Jonathan Allen

6
+1 Di aplikasi keuangan (di mana-mana, tidak hanya di bank), tidak ada pembaruan atau penghapusan. Bahkan operasi yang salah dikoreksi dengan memasukkan catatan. Apa istilah ini dalam bahasa Inggris? Apakah itu "storno"? Google tidak membantu saya untuk menjawab pertanyaan ini
Gennady Vanin Геннадий Ванин

7
Keterlambatan masuk ... kebuntuan harus ditangkap dan dicoba lagi. Bacaan kotor memiliki konsekuensi
gbn

4
@ JonathanAllen hanya fyi, istilahnya UTmost, bukan UP.
Jimmy D

57

Sayangnya ini bukan hanya tentang membaca data yang tidak dikomit. Di latar belakang Anda mungkin berakhir membaca halaman dua kali (dalam kasus split halaman), atau Anda mungkin kehilangan halaman sama sekali. Jadi hasil Anda mungkin sangat miring.

Lihat artikel Itzik Ben-Gan . Berikut ini kutipannya:

"Dengan petunjuk NOLOCK (atau mengatur tingkat isolasi sesi untuk BACA TIDAK DIKETAHUI), Anda memberi tahu SQL Server bahwa Anda tidak mengharapkan konsistensi, jadi tidak ada jaminan. Ingatlah bahwa" data tidak konsisten "tidak hanya berarti bahwa Anda mungkin melihat perubahan yang tidak dikomit yang kemudian digulirkan kembali, atau perubahan data dalam kondisi perantara transaksi. Ini juga berarti bahwa dalam kueri sederhana yang memindai semua data tabel / indeks SQL Server dapat kehilangan posisi pemindaian, atau Anda mungkin berakhir mendapatkan baris yang sama dua kali . "


5
Sedikit lebih jauh ke bawah ia menjelaskan cara mendapatkan baris yang sama dua kali: Saya akan membuat ulang tabel T1 sedemikian rupa sehingga indeks berkerumun pada col1 akan didefinisikan sebagai indeks unik dengan opsi IGNORE_DUP_KEY. Ini berarti bahwa nilai duplikat tidak bisa ada di col1, dan juga bahwa upaya untuk memasukkan kunci duplikat tidak akan gagal transaksi dan menghasilkan kesalahan, bukan hanya menghasilkan peringatan. Jika Anda tidak menggunakan opsi aneh ini, Anda mungkin tidak perlu khawatir mendapatkan baris dua kali
JanHudecek

Anda masih bisa mendapatkan baris dupe bahkan tanpa opsi kabel - jika kueri Anda memanfaatkan indeks yang tidak unik, misalnya. Ini bukan unik untuk nolock.
RMD

54

Contoh buku teks untuk penggunaan sah dari petunjuk nolock adalah pengambilan sampel laporan terhadap basis data OLTP yang tinggi.

Untuk mengambil contoh topikal. Jika bank jalanan AS yang besar ingin menjalankan laporan per jam mencari tanda-tanda pertama tingkat kota berjalan di bank, kueri nolock dapat memindai tabel transaksi yang menjumlahkan setoran tunai dan penarikan tunai per kota. Untuk laporan seperti itu, persentase kesalahan kecil yang disebabkan oleh transaksi pembaruan yang dibatalkan tidak akan mengurangi nilai laporan.


31

Tidak yakin mengapa Anda tidak membungkus transaksi keuangan dalam transaksi basis data (seperti ketika Anda mentransfer dana dari satu akun ke akun lainnya - Anda tidak melakukan satu sisi transaksi pada suatu waktu - inilah mengapa transaksi eksplisit ada). Bahkan jika kode Anda adalah braindead untuk transaksi bisnis seperti apa adanya, semua database transaksional memiliki potensi untuk melakukan kembalikan secara implisit jika terjadi kesalahan atau kegagalan. Saya pikir diskusi ini jauh di atas kepala Anda.

Jika Anda mengalami masalah penguncian, terapkan versi dan bersihkan kode Anda.

Tidak ada kunci tidak hanya mengembalikan nilai yang salah itu mengembalikan catatan hantu dan duplikat.

Ini adalah kesalahpahaman umum bahwa selalu membuat kueri berjalan lebih cepat. Jika tidak ada kunci tulis di atas meja, itu tidak ada bedanya. Jika ada kunci di atas meja, itu dapat membuat kueri lebih cepat, tetapi ada alasan kunci diciptakan di tempat pertama.

Dalam keadilan, berikut adalah dua skenario khusus di mana petunjuk nolock dapat memberikan utilitas

1) Database server pra-2005 sql yang perlu menjalankan kueri panjang terhadap database OLTP langsung, ini mungkin satu-satunya cara

2) Aplikasi yang ditulis dengan buruk yang mengunci catatan dan mengembalikan kontrol ke UI dan pembaca diblokir tanpa batas waktu. Nolock dapat membantu di sini jika aplikasi tidak dapat diperbaiki (pihak ketiga dll) dan basis datanya baik sebelum 2005 atau versi tidak dapat dinyalakan.


11
Saya setuju dengan Anda bahwa NOLOCK tidak boleh digunakan untuk menebus kode yang ditulis dengan buruk. Namun, saya pikir serangan Anda terhadap Johnathan tidak beralasan karena ia tidak pernah benar-benar menyebutkan transaksi basis data . Dia hanya menunjukkan bahwa aplikasi keuangan biasanya tidak memungkinkan pengeditan untuk mencatat (jelas ada beberapa pengecualian). Dalam contoh transfer dana Anda, dia mengatakan akan aneh jika Anda mengubah nilai saldo akun alih-alih menambahkan entri debit / kredit ke jenis buku besar.
chrnola

19
Ketika dana ditransfer dari satu rekening ke rekening lain di bank yang berbeda, menurut Anda apa yang terjadi? Beberapa uber-database mengambil kunci di atas meja di Bank of America dan lainnya di Wells Fargo? Tidak. Transaksi keuangan ditulis untuk masing-masing dan kemudian proses akhir hari memverifikasi bahwa semua catatan cocok.
Jonathan Allen

24

NOLOCKsetara dengan READ UNCOMMITTED, namun Microsoft mengatakan Anda tidak boleh menggunakannya untuk UPDATEatau DELETEpernyataan:

Untuk pernyataan UPDATE atau DELETE: Fitur ini akan dihapus dalam versi Microsoft SQL Server yang akan datang. Hindari menggunakan fitur ini dalam pekerjaan pengembangan baru, dan rencanakan untuk memodifikasi aplikasi yang saat ini menggunakan fitur ini.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Artikel ini berlaku untuk SQL Server 2005, jadi dukungan untuk NOLOCKada jika Anda menggunakan versi itu. Agar kode Anda terbukti di masa mendatang (dengan asumsi Anda telah memutuskan untuk menggunakan pembacaan kotor) Anda dapat menggunakan ini dalam prosedur tersimpan Anda:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


21

Anda dapat menggunakannya saat Anda hanya membaca data, dan Anda tidak terlalu peduli apakah Anda mungkin mendapatkan kembali data yang belum berkomitmen.

Ini bisa lebih cepat pada operasi baca, tetapi saya tidak bisa mengatakan berapa banyak.

Secara umum, saya sarankan agar tidak menggunakannya - membaca data yang tidak dikomit bisa sedikit membingungkan.


1
alangkah baiknya jika Anda menyebutkan fakta bahwa SQL Server 2005 memiliki versi baris sehingga nolocks bahkan tidak diperlukan lagi.
Jonathan Allen

Yah, "dengan (nolock)" masih ada tempatnya bahkan di SQL Server 2005 - tetapi manfaatnya semakin ramping, itu benar.
marc_s

18

Kasus lain di mana biasanya tidak apa-apa adalah dalam database pelaporan, di mana data mungkin sudah berumur dan penulisan tidak terjadi. Namun, dalam kasus ini, opsi harus ditetapkan pada tingkat basis data atau tabel oleh administrator dengan mengubah tingkat isolasi standar.

Dalam kasus umum: Anda dapat menggunakannya saat Anda sangat yakin tidak masalah membaca data lama. Yang penting untuk diingat adalah sangat mudah untuk mendapatkan kesalahan itu . Misalnya, meskipun tidak apa-apa saat Anda menulis kueri, apakah Anda yakin ada sesuatu yang tidak akan berubah di basis data di masa depan untuk menjadikan pembaruan ini lebih penting?

Saya juga akan 2nd berpendapat bahwa itu mungkin bukan ide yang baik di aplikasi perbankan. Atau aplikasi inventaris. Atau di mana pun Anda berpikir tentang transaksi.


4
Sebagai orang yang bekerja pada aplikasi perbankan, saya harus mengatakan tidak ada kunci tidak masalah. Catatan transaksional, yaitu baris yang dimasukkan tetapi tidak pernah diperbarui atau dihapus, mengejutkan resisten terhadap masalah membaca data yang tidak dikomit.
Jonathan Allen

15

Jawaban sederhana - setiap kali SQL Anda tidak mengubah data, dan Anda memiliki kueri yang mungkin mengganggu aktivitas lain (melalui penguncian).

Sebaiknya pertimbangkan permintaan apa pun yang digunakan untuk laporan, terutama jika kueri membutuhkan waktu lebih dari, katakanlah, 1 detik.

Ini sangat berguna jika Anda memiliki laporan tipe OLAP yang Anda jalankan terhadap basis data OLTP.

Namun, pertanyaan pertama yang diajukan adalah "mengapa saya mengkhawatirkan hal ini?" Dalam pengalaman saya, memalsukan perilaku penguncian standar sering terjadi ketika seseorang dalam mode "coba apa saja" dan ini adalah satu kasus di mana konsekuensi yang tidak terduga tidak kecil kemungkinannya. Terlalu sering itu adalah kasus optimasi prematur dan terlalu mudah dibiarkan tertanam dalam aplikasi "berjaga-jaga." Penting untuk memahami mengapa Anda melakukannya, masalah apa yang dipecahkan, dan apakah Anda benar-benar memiliki masalah.


11

Jawaban singkat:

Hanya digunakan WITH (NOLOCK)dalam pernyataan SELECT pada tabel yang memiliki indeks berkerumun.

Jawaban panjang:

WITH (NOLOCK) sering dieksploitasi sebagai cara ajaib untuk mempercepat pembacaan basis data.

Rangkaian hasil dapat berisi baris yang belum dikomit, yang sering kali dibatalkan.

Jika WITH (NOLOCK) diterapkan ke tabel yang memiliki indeks non-clustered maka indeks baris dapat diubah oleh transaksi lain karena data baris sedang dialirkan ke tabel hasil. Ini berarti bahwa set hasil dapat berupa baris yang hilang atau menampilkan baris yang sama beberapa kali.

READ COMMITTED menambahkan masalah tambahan di mana data rusak dalam satu kolom di mana banyak pengguna mengubah sel yang sama secara bersamaan.


2
Membaca data yang tidak berkomitmen dapat diterima jika tidak mengubah keputusan akhir. Misalnya, jika Anda mencoba memproyeksikan berapa banyak uang yang akan dihasilkan toko ritel Anda selama 6 bulan ke depan, melihat bahwa Tammy membeli 2 gulungan tisu ketika ia benar-benar membeli 3 tidak akan mengubah pendapat Anda tentang masa depan. .
Jonathan Allen

1
Jika filter Anda termasuk sekarang, data Anda akan menjadi tidak akurat saat Anda menjalankan kueri. Jika filter Anda hanya menyertakan data historis, menggunakan READ UNCOMITTED tidak akan memengaruhi sama sekali. Ada alasan mengapa itu dimasukkan dalam standar ANSI.
Jonathan Allen

2
Jangan pernah bilang tidak akan pernah. Jika Anda MEMBUTUHKAN data menjadi 100% akurat, maka Anda tidak boleh menggunakan nolock. Bagi saya, ini biasanya tidak terjadi. Ketika menyajikan data kepada pengguna, pada saat mereka bertindak pada data, itu mungkin sudah berubah, tetapi kemungkinan besar tidak, dan pertikaian kunci tidak sebanding dengan keterlambatan respons.
Perposterer

Mari kita berpegang pada sistem yang layak ada. Jangan lupa bahwa Tammy memiliki otak yang sangat baik, jadi menggunakan database untuk mencatat pembelian handuk kertas kecil yang tidak diperhatikan oleh siapa pun adalah hal terbaik. Fokus kami adalah sistem yang benar-benar penting misalnya membuat orang dibayar tepat waktu, menanggapi keadaan darurat, dll. Sangat bermanfaat bahwa penggunaan WITH (NOLOCK) dipahami oleh orang-orang yang memprogram sistem apa pun yang layak keberadaannya. Ketika seseorang dapat melakukan pekerjaan yang lebih baik daripada database maka pertimbangkan untuk menggunakan kembali sumber daya tersebut.
WonderWorker

10

2 sen saya - masuk akal untuk digunakan WITH (NOLOCK) ketika Anda perlu membuat laporan. Pada titik ini, data tidak akan banyak berubah & Anda tidak ingin mengunci catatan itu.


2
Saya pikir DENGAN (NoLOCK) lebih baik jika Anda tidak peduli dengan perubahan saat ini.
Abdul Saboor

9

Jika Anda menangani transaksi keuangan maka Anda tidak akan pernah ingin menggunakannya nolock. nolockpaling baik digunakan untuk memilih dari tabel besar yang memiliki banyak pembaruan dan Anda tidak peduli jika catatan yang Anda dapatkan mungkin sudah ketinggalan zaman.

Untuk catatan keuangan (dan hampir semua catatan lainnya di sebagian besar aplikasi) nolockakan mendatangkan malapetaka karena Anda berpotensi membaca kembali data dari catatan yang sedang ditulis dan tidak mendapatkan data yang benar.


5
Anehnya, ketika bekerja dengan data keuangan ini bukan masalah. Karena baris tidak pernah diedit dan akun direkonsiliasi pada akhir hari, membaca data palsu sementara tidak melakukan apa-apa.
Jonathan Allen

8

Saya sudah terbiasa mengambil "batch berikutnya" untuk melakukan sesuatu. Dalam hal ini tidak masalah item mana yang tepat, dan saya memiliki banyak pengguna yang menjalankan kueri yang sama ini.


1
Kami melakukan sesuatu yang mirip dengan menyajikan tugas latar belakang dengan antrian pekerjaan yang harus dilakukan. Jika, ketika sampai ke catatan tertentu itu tidak lagi ada / cocok dengan kriteria pemilihan, itu hanya pindah ke yang berikutnya.
TripeHound

7

Gunakan nolock ketika Anda setuju dengan data "kotor". Yang berarti nolock juga dapat membaca data yang sedang dalam proses modifikasi dan / atau data yang tidak dikomit.

Ini umumnya bukan ide yang baik untuk menggunakannya dalam lingkungan transaksi yang tinggi dan itulah sebabnya itu bukan opsi default pada permintaan.


3
Satu-satunya waktu yang Anda butuhkan adalah dalam lingkungan transaksi yang tinggi. Jika tabel Anda sebagian besar tidak digunakan, maka Anda tidak akan mendapatkan apa pun darinya.
Jonathan Allen

7

Saya menggunakan dengan petunjuk (nolock) khususnya dalam database SQLServer 2000 dengan aktivitas tinggi. Saya tidak yakin bahwa itu diperlukan dalam SQL Server 2005. Saya baru-baru ini menambahkan petunjuk itu dalam SQL Server 2000 atas permintaan DBA klien, karena dia memperhatikan banyak kunci catatan SPID.

Yang bisa saya katakan adalah bahwa menggunakan petunjuk TIDAK menyakiti kita dan tampaknya telah membuat masalah penguncian menyelesaikannya sendiri. DBA pada klien tertentu itu pada dasarnya bersikeras bahwa kami menggunakan petunjuk itu.

Omong-omong, basis data yang saya tangani adalah back-end untuk sistem klaim medis perusahaan, jadi kita berbicara tentang jutaan catatan dan 20+ tabel di banyak gabungan. Saya biasanya menambahkan petunjuk WITH (nolock) untuk setiap tabel dalam gabungan (kecuali jika itu adalah tabel turunan, dalam hal ini Anda tidak dapat menggunakan petunjuk tertentu)


1
SQL Server 2005 menambahkan "versi baris" yang seharusnya sangat mengurangi kebutuhan untuk nolocks. Kami baru-baru ini ditingkatkan dan tidak sedang melatih DBA kami untuk berhenti menggunakannya.
Jonathan Allen

5

Jawaban paling sederhana adalah pertanyaan sederhana - apakah Anda perlu agar hasilnya berulang? Jika ya maka NOLOCKS tidak sesuai dalam kondisi apa pun

Jika Anda tidak membutuhkan pengulangan maka nolocks mungkin berguna, terutama jika Anda tidak memiliki kendali atas semua proses yang terhubung ke database target.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.