Apakah NOLOCK (Sql Server hint) merupakan praktik yang buruk?


125

Saya berkecimpung dalam bisnis membuat situs web dan aplikasi yang tidak memiliki misi penting -> mis. perangkat lunak perbankan, penerbangan luar angkasa, aplikasi pemantauan perawatan intensif, dll. Anda mengerti.

Jadi, dengan disclaimer besar-besaran itu, apakah menggunakan petunjuk NOLOCK di beberapa pernyataan Sql itu buruk? Beberapa tahun yang lalu, telah disarankan oleh sesama Administrator Sql bahwa saya harus menggunakan NOLOCK jika saya senang dengan "bacaan kotor" yang akan memberi saya kinerja sedikit lebih banyak dari sistem saya karena setiap pembacaan tidak mengunci tabel / baris / apa saja.

Saya juga diberi tahu bahwa ini adalah solusi yang bagus jika saya mengalami jalan buntu. Jadi, saya mulai mengikuti pemikiran itu selama beberapa tahun sampai seorang guru Sql membantu saya dengan beberapa kode acak dan memperhatikan semua NOLOCKS dalam kode sql saya. Saya dimarahi dengan sopan dan dia mencoba menjelaskannya kepada saya (mengapa itu bukan hal yang baik) dan saya agak tersesat. Saya merasa bahwa inti dari penjelasannya adalah 'ini adalah solusi bantuan pita untuk masalah yang lebih serius .. terutama jika Anda mengalami jalan buntu. Karena itu, perbaiki akar masalahnya '.

Saya melakukan beberapa googling baru-baru ini tentang hal itu dan menemukan posting ini .

Jadi, bisakah guru sensei db sql mencerahkan saya?


Saya tidak mengerti Sam, Anda mengatakan gunakan isolasi Snapshot jika itu adalah situs web yang banyak dibaca. Tapi kemudian kamu mengatakan SO melakukan itu, dan itu buruk? atau hanya penggunaan NOLOCK?
Pure.Krome

Jawaban:


67

Dengan petunjuk NOLOCK, tingkat isolasi transaksi untuk SELECTpernyataan tersebut adalah READ UNCOMMITTED. Artinya, kueri mungkin melihat data yang kotor dan tidak konsisten.

Ini bukan ide yang baik untuk diterapkan sebagai aturan. Sekalipun perilaku baca kotor ini OK untuk aplikasi berbasis web penting misi Anda, pemindaian NOLOCK dapat menyebabkan kesalahan 601 yang akan menghentikan kueri karena pergerakan data sebagai akibat dari kurangnya perlindungan penguncian.

Saya sarankan membaca When Snapshot Isolation Helps and When It Hurts - MSDN merekomendasikan penggunaan READ COMMITTED SNAPSHOT daripada SNAPSHOT dalam banyak situasi.


1
Rex, jangan ragu untuk menambahkan catatan tentang isolasi snapshot.
Sam Saffron

2
Ya, Sam mengatakan isolasi Snapshot dan Anda menyarankan Snapshot Read Committed. Saya menjadi sangat bingung: P (dan saya belum mempelajari artikelnya, juga!)
Pure.Krome

2
Ini kadang-kadang berguna, tetapi biasanya tidak untuk produksi. Saya sering menggunakannya untuk mengambil sampel data untuk diuji dengan atau untuk menghasilkan laporan di mana saya sangat peduli tentang urutan kasar besarnya di mana pembacaan kotor tidak masalah.
TimothyAWiseman

NOLOCK == saya tidak peduli jika baris yang dikomit terlewatkan, baris yang tidak dikomit disertakan, dalam kasus yang jarang terjadi, baris yang sama dikembalikan lebih dari sekali, dan dalam kasus yang sangat jarang baris dikembalikan yang tidak cocok dengan kueri saya. (lihat blogs.msdn.com/b/sqlcat/archive/2007/02/01/… , ditemukan dari SO q'n lain tentang topik ini)
Andrew Hill

106

Sebelum mengerjakan Stack Overflow, saya menentang NOLOCKprinsip bahwa Anda berpotensi melakukan SELECTdengan NOLOCKdan mendapatkan kembali hasil dengan data yang mungkin kedaluwarsa atau tidak konsisten. Faktor yang perlu dipikirkan adalah berapa banyak catatan yang dapat disisipkan / diperbarui pada saat yang sama proses lain mungkin memilih data dari tabel yang sama. Jika ini sering terjadi, kemungkinan besar terjadi kebuntuan kecuali Anda menggunakan mode database seperti READ COMMITED SNAPSHOT.

Saya telah mengubah perspektif saya tentang penggunaan NOLOCKsetelah menyaksikan bagaimana hal itu dapat meningkatkan SELECTkinerja serta menghilangkan kebuntuan pada SQL Server yang dimuat secara masif. Ada kalanya Anda mungkin tidak peduli bahwa data Anda tidak benar-benar 100% berkomitmen dan Anda memerlukan hasil secepatnya meskipun mungkin sudah usang.

Ajukan pertanyaan pada diri Anda sendiri saat berpikir untuk menggunakan NOLOCK:

Apakah kueri saya menyertakan tabel yang memiliki jumlah INSERT/ UPDATEperintah yang tinggi dan apakah saya peduli jika data yang dikembalikan dari kueri mungkin kehilangan perubahan ini pada saat tertentu?

Jika jawabannya tidak, gunakan NOLOCKuntuk meningkatkan kinerja.


Saya baru saja melakukan pencarian cepat untuk NOLOCKkata kunci dalam basis kode untuk Stack Overflow dan menemukan 138 contoh, jadi kami menggunakannya di beberapa tempat.


7
IMO, Ini agak sederhana. Kebuntuan dapat dihilangkan dengan menggunakan indeks penutup, menghilangkan tekanan dari indeks Tergugus.
Mitch Wheat

8
Saya tidak ingin mengurangi pentingnya cakupan indeks yang baik. Ada kalanya kueri yang menggunakan NOLOCK dapat menambah kinerja tambahan selain keuntungan yang direalisasikan oleh indeks pada tabel dengan jumlah penyisipan / pembaruan yang tinggi. Kecepatan kueri pada Stack Overflow adalah yang terpenting bahkan dengan mengorbankan data yang tidak akurat atau hilang.
Geoff Dalgas

9
Rupanya seseorang bisa mendapatkan baris duplikat menggunakan NOLOCK. Ini berarti saya harus meremehkan jawaban Anda. Maaf.
ErikE

1
@MitchWheat A SELECT, hanya membaca dari indeks sampul , dapat menyebabkan kebuntuan. SPID 1) mulai SELECTdari indeks penutup. SPID 2) Mulai UPDATEmeja. Perbarui kemudian pindah ke memperbarui indeks penutup. UPDATEmencapai kisaran indeks yang dikunci oleh SELECTdan menjadi diblokir. SPID 1) masih mencari melalui indeks penutup, menemukan kisaran yang dikunci oleh UPDATEdan menjadi diblokir. MATI . Tidak ada yang bisa menyelesaikan kebuntuan itu (kecuali menangkap kesalahan SQL Server 1205, dan secara otomatis mencoba kembali, atau menggunakan NOLOCK)
Ian Boyd

2
Saya pikir hal penting yang perlu diperhatikan tentang jawaban ini adalah sesuai dengan masalah yang dihadapi . Bergantung pada aplikasi Anda, risiko data basi / tidak terikat / duplikat / hilang mungkin tidak sebanding dengan pengorbanannya.
Pengembang Holistik

20

Jika Anda tidak peduli dengan bacaan kotor (yaitu dalam situasi yang didominasi BACA), maka NOLOCKtidak masalah.

TAPI , ketahuilah bahwa sebagian besar masalah penguncian adalah karena tidak memiliki indeks yang 'benar' untuk beban kerja kueri Anda (dengan asumsi perangkat keras siap untuk tugas tersebut).

Dan penjelasan gurunya benar. Biasanya ini merupakan solusi perban untuk masalah yang lebih serius.

Sunting : Saya jelas tidak menyarankan agar NOLOCK digunakan. Saya kira saya seharusnya menjelaskannya dengan jelas. (Saya hanya akan menggunakannya, dalam keadaan ekstrim di mana saya telah menganalisis bahwa itu OK). Sebagai contoh, beberapa waktu lalu saya mengerjakan beberapa TSQL yang telah ditaburi NOLOCK untuk mencoba dan mengatasi masalah penguncian. Saya menghapus semuanya, menerapkan indeks yang benar, dan SEMUA kebuntuan hilang.


3
Hmm .. Saya masih belum mengerti. Jadi tidak apa-apa, tapi itu juga bentuk yang buruk .. itukah yang kamu katakan?
Pure.Krome

Dengan asumsi bahwa Anda TIDAK PERNAH peduli dengan bacaan kotor, maka tidak ada salahnya. TAPI biasanya kasus mengobati gejala dan bukan penyebabnya ...
Mitch Wheat

2
Saya rasa rexemnya tidak adil hanya downvoting, saya pikir Anda tidak mengatasi kesalahan sembarangan yang hanya muncul saat Anda menggunakan nolock. Tidaklah baik untuk mendapatkan halaman kesalahan kosong sesekali di situs Anda, itu adalah bentuk yang sangat buruk. Saya tidak suka pernyataan bahwa "jika Anda tidak peduli dengan bacaan kotor tidak apa-apa" ... tidak baik, bahkan jika Anda tidak peduli dengan bacaan kotor
Sam Saffron

Halaman kosong yang Anda dapatkan saat kueri menghasilkan pengecualian yang logika percobaan ulangnya tidak Anda implementasikan. Apa yang terjadi di situs Anda ketika hasil eksekusi kueri dengan pengecualian, apakah Anda memiliki logika coba lagi di mana-mana?
Sam Saffron

Ambil kueri yang dioptimalkan dengan sangat baik yang Anda tahu mencapai indeks yang tepat. Kemudian tambahkan petunjuk nolock dan lihat itu menjadi lebih cepat. Jika Anda tidak peduli dengan bacaan kotor, Anda tidak akan pernah melukai diri sendiri menggunakan nolock.
Hardwareguy

13

Meragukan itu adalah "guru" yang memiliki pengalaman dalam lalu lintas tinggi ...

Situs web biasanya "kotor" pada saat orang itu melihat laman yang dimuat sepenuhnya. Pertimbangkan formulir yang dimuat dari database dan kemudian menyimpan data yang diedit ?? Sungguh konyol cara orang terus-menerus mengatakan bahwa bacaan kotor seperti itu tidak, tidak.

Meskipun demikian, jika Anda memiliki sejumlah lapisan yang dibangun di atas pilihan Anda, Anda bisa membangun dalam redundansi yang berbahaya. Jika Anda berurusan dengan uang atau skenario status, maka Anda tidak hanya membutuhkan pembacaan / penulisan data transaksional, tetapi juga solusi konkurensi yang tepat (sesuatu yang kebanyakan "ahli" tidak peduli).

Di sisi lain, jika Anda memiliki pencarian produk lanjutan untuk sebuah situs web (yaitu sesuatu yang kemungkinan besar tidak akan disimpan dalam cache dan menjadi sedikit intensif) dan Anda pernah membangun sebuah situs dengan lebih dari beberapa pengguna secara bersamaan (secara fenomenal berapa banyak "ahli" belum), sangat konyol untuk mengabaikan setiap proses lain di belakangnya.

Ketahui artinya dan gunakan jika perlu. Basis data Anda akan hampir selalu menjadi penghambat utama Anda hari ini dan menjadi pintar dalam menggunakan NOLOCK dapat menghemat ribuan infrastruktur.

EDIT: Ini bukan hanya kebuntuan, tetapi juga seberapa banyak Anda akan membuat orang lain menunggu sampai Anda selesai, atau sebaliknya.

Menggunakan Petunjuk NOLOCK di EF4?


10

Tidak ada jawaban yang salah, betapapun sedikit membingungkan mungkin.

  • Saat menanyakan nilai / baris tunggal, selalu praktik yang buruk untuk menggunakan NOLOCK - Anda mungkin tidak ingin menampilkan informasi yang salah atau bahkan mungkin mengambil tindakan apa pun pada data yang salah.
  • Saat menampilkan informasi statistik kasar, NOLOCK bisa sangat berguna. Ambil SO sebagai contoh: Tidak masuk akal untuk mengambil kunci untuk membaca jumlah pasti dari sebuah pertanyaan, atau jumlah pertanyaan yang tepat untuk sebuah tag. Tidak ada yang peduli jika Anda salah menyatakan 3360 pertanyaan dengan tag "sql-server" sekarang, dan karena transaksi rollback, 3359 pertanyaan satu detik kemudian.

Saya sama sekali tidak setuju dengan poin pertama Anda. JIKA Anda menanyakan nilai / baris tunggal, dan Anda menentukan id unik untuk baris tersebut, dan Anda tahu bahwa tidak ada proses lain yang akan mengaksesnya, maka menggunakan nolock dapat diterima dengan baik, dan mengurangi pemblokiran dalam aplikasi bersamaan.
tuseau

1
Tidak. Baris mungkin berubah karena alasan lain, misalnya menyisipkan baris lain akan memisahkan halaman. Pengindeksan yang tepat, Read Committed Snapshot, dan Snapshot Isolation hampir selalu merupakan ide yang lebih baik.
Mark Sowul

1
@tuseau jika Anda "tahu" bahwa tidak ada proses lain yang akan mengakses baris tersebut, tindakan mengambil kunci tidak akan memblokir apa pun, jadi Anda (secara praktis) tidak mengeluarkan biaya apa pun,
Andrew Hill

2

Sebagai Pengembang profesional, menurut saya itu tergantung. Tapi saya pasti mengikuti saran GATS dan OMG Ponies. Ketahui Apa yang Anda lakukan, ketahui kapan itu membantu dan kapan itu menyakitkan dan

membaca petunjuk dan ide buruk lainnya

Apa yang mungkin membuat Anda memahami sql server lebih dalam. Saya biasanya mengikuti aturan bahwa Petunjuk SQL adalah JAHAT, tetapi sayangnya saya menggunakannya sesekali ketika saya bosan dengan memaksa server SQL melakukan sesuatu ... Tetapi ini adalah kasus yang jarang terjadi.

luke


2

Ketika dukungan aplikasi ingin menjawab pertanyaan ad-hock dari server produksi menggunakan SSMS (yang tidak dipenuhi melalui pelaporan) saya meminta mereka menggunakan nolock. Dengan begitu bisnis 'utama' tidak terpengaruh.


2

Saya setuju dengan beberapa komentar tentang petunjuk NOLOCK dan terutama dengan yang mengatakan "gunakan bila perlu". Jika aplikasi ditulis dengan buruk dan menggunakan cara yang tidak sesuai konkurensi - yang dapat menyebabkan eskalasi kunci. Tabel yang sangat transaksional juga terkunci sepanjang waktu karena sifatnya. Memiliki cakupan indeks yang baik tidak akan membantu dalam mengambil data, tetapi menyetel ISOLATION LEVEL ke READ UNCOMMITTED akan membantu. Saya juga percaya bahwa menggunakan petunjuk NOLOCK aman dalam banyak kasus ketika sifat perubahan dapat diprediksi. Misalnya - di bidang manufaktur ketika pekerjaan dengan wisatawan melalui proses yang berbeda dengan banyak sisipan pengukuran, Anda dapat dengan aman mengeksekusi kueri terhadap pekerjaan yang sudah selesai dengan petunjuk NOLOCK dan dengan cara ini menghindari tabrakan dengan sesi lain yang menempatkan kunci PROMOTED atau EKSKLUSIF di atas meja /halaman. Data yang Anda akses dalam hal ini bersifat statis, tetapi mungkin berada dalam tabel yang sangat transaksional dengan ratusan juta catatan dan ribuan pembaruan / sisipan per menit. Bersulang


2

Saya percaya bahwa menggunakan nolock hampir tidak pernah benar.

Jika Anda membaca satu baris, maka indeks yang benar berarti Anda tidak memerlukan NOLOCK karena tindakan baris individual diselesaikan dengan cepat.

Jika Anda membaca banyak baris untuk apa pun selain tampilan sementara, dan peduli untuk dapat mengulangi hasil, atau mempertahankan nomor yang dihasilkan, maka NOLOCK tidak sesuai.

NOLOCK adalah tag pengganti untuk "saya tidak peduli jika jawaban ini berisi baris duplikat, baris yang dihapus, atau baris yang tidak pernah disisipkan sejak awal karena rollback"

Kesalahan yang mungkin terjadi di bawah NOLOCK:

  • Baris yang cocok tidak dikembalikan sama sekali.
  • baris tunggal dikembalikan beberapa kali (termasuk beberapa contoh dari kunci utama yang sama)
  • Baris yang tidak cocok dikembalikan.

Tindakan apa pun yang dapat menyebabkan halaman terbelah saat pemilihan noLock sedang berjalan dapat menyebabkan hal-hal ini terjadi. Hampir semua tindakan (bahkan penghapusan) dapat menyebabkan halaman terbelah.

Oleh karena itu: jika Anda "tahu" bahwa baris tidak akan diubah saat Anda berjalan, jangan gunakan nolock, karena indeks akan memungkinkan pengambilan yang efisien.

Jika Anda menduga baris tersebut dapat berubah saat kueri sedang berjalan, dan Anda peduli dengan keakuratannya, jangan gunakan nolock.

Jika Anda mempertimbangkan NOLOCK karena kebuntuan, periksa struktur rencana kueri untuk pemindaian tabel yang tidak terduga, lacak kebuntuan dan lihat mengapa hal itu terjadi. NOLOCK seputar penulisan dapat berarti bahwa kueri yang sebelumnya menemui jalan buntu berpotensi menulis jawaban yang salah.


2

Solusi yang lebih baik, jika memungkinkan adalah:

  • Gandakan data Anda (menggunakan replikasi log) ke database pelaporan.
  • Gunakan snapshot SAN dan pasang versi DB yang konsisten
  • Gunakan database yang memiliki tingkat isolasi transaksi fundamental yang lebih baik

Tingkat isolasi transaksi SNAPSHOT dibuat karena MS kehilangan penjualan ke Oracle. Oracle menggunakan log undo / redo untuk menghindari masalah ini. Postgres menggunakan MVCC. Di masa depan, MS Heckaton akan menggunakan MVCC, tapi itu beberapa tahun lagi untuk siap produksi.


Ada kesalahan ketik di atas. Maksud saya, "mekanisme isolasi transaksi fundamental yang lebih baik".
pwy

1
Tingkat isolasi transaksi SNAPSHOT adalah penemuan MS. Pada dasarnya ini menempatkan data dalam tabel temp di TEMPDB. DB itu dibagi di antara semua DB di kotak. Jadi, Anda ingin menggunakan SSD untuk TEMPDB jika memungkinkan. Itu mungkin lebih sedikit usaha daripada opsi lainnya.
pwy

1

NOLOCK sering dieksploitasi sebagai cara ajaib untuk mempercepat pembacaan database, tetapi saya mencoba untuk menghindari penggunaannya sebisa mungkin.

Kumpulan hasil dapat berisi baris yang belum dikomit, yang sering kali kemudian diputar kembali.

Kesalahan atau kumpulan Hasil bisa kosong, baris hilang atau menampilkan baris yang sama beberapa kali.

Ini karena transaksi lain memindahkan data pada saat yang sama Anda membacanya.

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


-2

Dalam kehidupan nyata di mana Anda menemukan sistem yang sudah ditulis dan menambahkan indeks ke tabel kemudian secara drastis memperlambat pemuatan data dari tabel data 14gig, Anda kadang-kadang dipaksa untuk menggunakan DENGAN NOLOCK pada laporan Anda dan pemrosesan akhir bulan sehingga fungsi agregat (jumlah , hitung dll) jangan lakukan penguncian baris, halaman, tabel dan merusak kinerja keseluruhan. Mudah dikatakan dalam sistem baru, jangan pernah menggunakan DENGAN NOLOCK dan menggunakan indeks - tetapi menambahkan indeks sangat menurunkan tingkat pemuatan data, dan ketika saya diberitahu, yah, ubah basis kode untuk menghapus indeks, lalu muat massal lalu buat ulang indeks - yang mana semuanya baik-baik saja, jika Anda mengembangkan sistem baru. Tetapi Tidak jika Anda sudah memiliki sistem.


1
apa yang kamu katakan
Max Alexander Hanna
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.