Có gì với (nolock) trong máy chủ SQL?


610

Ai đó có thể giải thích ý nghĩa của việc sử dụng with (nolock)trên các truy vấn, khi nào bạn nên / không nên sử dụng nó?

Ví dụ: nếu bạn có một ứng dụng ngân hàng có tỷ lệ giao dịch cao và nhiều dữ liệu trong một số bảng nhất định, thì loại truy vấn nào sẽ không ổn? Có những trường hợp khi bạn nên luôn luôn sử dụng nó / không bao giờ sử dụng nó?



1
một liên kết tại đây - mssqltips.com/sqlservertip/2470/NH
Steam

1
Dưới đây là một bản tóm tắt tuyệt vời về ý nghĩa của việc sử dụng blog NOLOCK.msdn.com/b/davidlean/archive/2009/04/06/ trộm
Bryan

Câu trả lời:


461

VỚI (NOLOCK) tương đương với việc sử dụng READ UNCOMMITED làm mức cô lập giao dịch. Vì vậy, bạn có nguy cơ đọc một hàng không được cam kết mà sau đó được khôi phục, tức là dữ liệu không bao giờ được đưa vào cơ sở dữ liệu. Vì vậy, trong khi nó có thể ngăn việc đọc bị bế tắc bởi các hoạt động khác, nó đi kèm với rủi ro. Trong một ứng dụng ngân hàng có tỷ lệ giao dịch cao, có lẽ nó sẽ không phải là giải pháp phù hợp cho bất kỳ vấn đề nào bạn đang cố gắng giải quyết với IMHO.


156
Hầu hết các ứng dụng ngân hàng có thể sử dụng nolock một cách an toàn vì chúng là giao dịch theo nghĩa kinh doanh. Bạn chỉ viết các hàng mới, bạn không bao giờ cập nhật chúng.
Jonathan Allen

49
@ Grauenwolf- Một hàng được chèn nhưng không được cam kết vẫn có thể dẫn đến việc đọc bẩn.
saasman

16
@ Saasman- Nếu bạn không bao giờ quay lại giao dịch, điều đó không thành vấn đề. Và với một bảng chỉ chèn, cơ hội quay trở lại là không có gì. Và nếu chúng xảy ra, bạn vẫn sẽ sửa tất cả trong báo cáo phương sai cuối ngày.
Jonathan Allen

1
Tôi cố thủ. Tôi giả sử Đã thêm không có gợi ý khóa. Dành cho Examp:
Ross Bush

11
Nếu bạn sử dụng NOLOCKvới một SELECTbạn sẽ có nguy cơ trả lại cùng một hàng nhiều lần (dữ liệu trùng lặp) nếu dữ liệu được chèn (hoặc cập nhật) vào bảng trong khi thực hiện chọn.
Ian Boyd

170

Câu hỏi là những gì tồi tệ hơn:

  • bế tắc, hoặc
  • một giá trị sai?

Đối với cơ sở dữ liệu tài chính, các bế tắc tồi tệ hơn nhiều so với các giá trị sai. Tôi biết rằng âm thanh ngược, nhưng nghe tôi nói. Ví dụ truyền thống về giao dịch DB là bạn cập nhật hai hàng, trừ đi một hàng và thêm vào một hàng khác. Điều đó là sai.

Trong một cơ sở dữ liệu tài chính, bạn sử dụng các giao dịch kinh doanh. Điều đó có nghĩa là thêm một hàng vào mỗi tài khoản. Điều quan trọng nhất là các giao dịch này hoàn thành và các hàng được viết thành công.

Lấy số dư tài khoản tạm thời sai không phải là một vấn đề lớn, đó là những gì kết thúc ngày hòa giải. Và một khoản thấu chi từ tài khoản có nhiều khả năng xảy ra do hai máy ATM đang được sử dụng cùng một lúc hơn là do không đọc được từ cơ sở dữ liệu.

Điều đó nói rằng, SQL Server 2005 đã sửa hầu hết các lỗi NOLOCKcần thiết. Vì vậy, trừ khi bạn đang sử dụng SQL Server 2000 hoặc sớm hơn, bạn không cần nó.

Đọc thêm
Phiên bản cấp hàng


22
Lấy số dư tài khoản tạm thời sai không phải là một vấn đề lớn? Điều gì xảy ra nếu giao dịch đó là giao dịch mà bạn đang rút tiền từ một máy rút tiền mà không có bất kỳ giới hạn thấu chi nào?
Học

13
@ Học tập: Điều gì xảy ra nếu bạn rút tiền 30 giây trước khi ai đó tính tiền vào thẻ của bạn? Cho đến khi tất cả các giao tiếp là turly tự nhiên, thấu chi sẽ là một thực tế của cuộc sống.
Jonathan Allen

6
+1 Trong ứng dụng tài chính (ở mọi nơi, không chỉ trong ngân hàng), không có cập nhật cũng không xóa. Ngay cả các hoạt động không chính xác được sửa chữa bằng cách chèn hồ sơ. Thuật ngữ này trong tiếng Anh là gì? Có phải là "storno"? Google đã không giúp tôi trả lời câu hỏi này
Gennady Vanin Геннадий Ванин

7
Nhập cảnh muộn ... những bế tắc nên được bắt và thử lại. Đọc bẩn có hậu quả
gbn

4
@Jonathan ALLen chỉ là một fyi, thuật ngữ này là tối đa, không phải LÊN.
Jimmy D

57

Thật không may, nó không chỉ là về việc đọc dữ liệu không được cam kết. Trong nền, bạn có thể kết thúc việc đọc các trang hai lần (trong trường hợp chia trang) hoặc bạn có thể bỏ lỡ các trang hoàn toàn. Vì vậy, kết quả của bạn có thể bị sai lệch.

Kiểm tra bài viết của Itzik Ben-Gan . Đây là một đoạn trích:

"Với gợi ý NOLOCK (hoặc đặt mức cô lập của phiên thành READ UNCOMMITTED), bạn nói với SQL Server rằng bạn không mong đợi tính nhất quán, vì vậy không có gì đảm bảo. Hãy nhớ rằng" dữ liệu không nhất quán "không chỉ có nghĩa là bạn có thể thấy các thay đổi không được cam kết sau đó được khôi phục hoặc thay đổi dữ liệu ở trạng thái trung gian của giao dịch. Điều đó cũng có nghĩa là trong một truy vấn đơn giản quét tất cả dữ liệu bảng / chỉ mục SQL Server có thể mất vị trí quét hoặc bạn có thể kết thúc nhận được cùng một hàng hai lần . "


5
Xa hơn một chút, anh giải thích cách lấy cùng một hàng hai lần: Tôi sẽ tạo lại bảng T1 sao cho chỉ mục được nhóm trên col1 sẽ được xác định là một chỉ mục duy nhất với tùy chọn IGNORE_DUP_KEY. Điều này có nghĩa là các giá trị trùng lặp không thể tồn tại trong col1 và cũng là một nỗ lực chèn khóa trùng lặp sẽ không làm hỏng giao dịch và tạo ra lỗi thay vì chỉ tạo cảnh báo. Nếu bạn không sử dụng tùy chọn kỳ lạ này, có lẽ bạn không phải lo lắng về việc nhận hàng hai lần
JanHudecek

Bạn vẫn có thể nhận được các hàng dupe ngay cả khi không có tùy chọn có dây - ví dụ: nếu truy vấn của bạn sử dụng một chỉ mục không phải là duy nhất. Điều này không phải là duy nhất cho nolock, mặc dù.
RMD

54

Ví dụ về sách giáo khoa cho việc sử dụng hợp pháp gợi ý nolock là lấy mẫu báo cáo dựa trên cơ sở dữ liệu OLTP cập nhật cao.

Để lấy một ví dụ chuyên đề. Nếu một ngân hàng đường phố lớn của Mỹ muốn chạy một báo cáo hàng giờ để tìm kiếm các dấu hiệu đầu tiên của cấp thành phố chạy trên ngân hàng, một truy vấn nolock có thể quét các bảng giao dịch tổng hợp tiền gửi và rút tiền mặt mỗi thành phố. Đối với một báo cáo như vậy, tỷ lệ lỗi nhỏ do các giao dịch cập nhật được khôi phục sẽ không làm giảm giá trị của báo cáo.


31

Không chắc chắn lý do tại sao bạn không gói các giao dịch tài chính trong các giao dịch cơ sở dữ liệu (như khi bạn chuyển tiền từ tài khoản này sang tài khoản khác - bạn không cam kết một mặt của giao dịch tại một thời điểm - đây là lý do tại sao các giao dịch rõ ràng tồn tại). Ngay cả khi mã của bạn được bổ sung cho các giao dịch kinh doanh vì nó có vẻ như vậy, tất cả các cơ sở dữ liệu giao dịch đều có khả năng thực hiện các lần khôi phục ngầm trong trường hợp xảy ra lỗi hoặc thất bại. Tôi nghĩ rằng cuộc thảo luận này là cách trên đầu của bạn.

Nếu bạn gặp vấn đề về khóa, hãy thực hiện phiên bản và dọn sạch mã của bạn.

Không có khóa không chỉ trả về các giá trị sai, nó trả về các bản ghi ảo và các bản sao.

Đó là một quan niệm sai lầm phổ biến rằng nó luôn làm cho các truy vấn chạy nhanh hơn. Nếu không có khóa ghi trên bàn, nó không tạo ra sự khác biệt nào. Nếu có các khóa trên bàn, nó có thể làm cho truy vấn nhanh hơn, nhưng có một lý do khóa được phát minh ở vị trí đầu tiên.

Công bằng, đây là hai kịch bản đặc biệt trong đó một gợi ý nolock có thể cung cấp tiện ích

1) Cơ sở dữ liệu máy chủ sql trước 2005 cần chạy truy vấn dài đối với cơ sở dữ liệu OLTP trực tiếp, đây có thể là cách duy nhất

2) Ứng dụng kém bằng văn bản khóa hồ sơ và trả lại quyền kiểm soát cho UI và trình đọc bị chặn vô thời hạn. Nolock có thể hữu ích ở đây nếu ứng dụng không thể được sửa chữa (bên thứ ba, v.v.) và cơ sở dữ liệu là trước năm 2005 hoặc không thể bật phiên bản.


11
Tôi đồng ý với bạn rằng NOLOCK không nên được sử dụng để bù cho mã được viết kém. Tuy nhiên, tôi nghĩ rằng cuộc tấn công Johnathan của bạn là không có cơ sở vì anh ta chưa bao giờ thực sự đề cập đến các giao dịch cơ sở dữ liệu . Ông chỉ đơn giản chỉ ra rằng các ứng dụng tài chính thường không cho phép chỉnh sửa hồ sơ (rõ ràng có một số ngoại lệ). Trong ví dụ về chuyển khoản của bạn, anh ta nói sẽ thật kỳ lạ nếu bạn thay đổi giá trị của số dư tài khoản thay vì thêm một mục ghi nợ / tín dụng vào sổ cái các loại.
chrnola

19
Khi tiền được chuyển từ tài khoản này sang tài khoản khác tại các ngân hàng khác nhau, bạn nghĩ điều gì sẽ xảy ra? Một số cơ sở dữ liệu uber có khóa trên một bảng tại Bank of America và một cái khác tại Wells Fargo? Không. Một giao dịch tài chính được viết cho mỗi và sau đó là một quy trình cuối ngày xác minh rằng tất cả các hồ sơ khớp với nhau.
Jonathan Allen

24

NOLOCKtương đương với READ UNCOMMITTED, tuy nhiên Microsoft nói rằng bạn không nên sử dụng nó cho UPDATEhoặc DELETEtuyên bố:

Đối với các câu lệnh CẬP NHẬT hoặc XÓA: Tính năng này sẽ bị xóa trong phiên bản tương lai của Microsoft SQL Server. Tránh sử dụng tính năng này trong công việc phát triển mới và lên kế hoạch sửa đổi các ứng dụng hiện đang sử dụng tính năng này.

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

Bài viết này áp dụng cho SQL Server 2005, vì vậy hỗ trợ NOLOCKtồn tại nếu bạn đang sử dụng phiên bản đó. Để chứng minh mã của bạn trong tương lai (giả sử bạn đã quyết định sử dụng các lần đọc bẩn), bạn có thể sử dụng mã này trong các quy trình được lưu trữ của mình:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


21

Bạn có thể sử dụng nó khi bạn chỉ đọc dữ liệu và bạn không thực sự quan tâm đến việc bạn có thể lấy lại dữ liệu chưa được cam kết hay không.

Nó có thể nhanh hơn trên một thao tác đọc, nhưng tôi thực sự không thể nói bao nhiêu.

Nói chung, tôi khuyên bạn không nên sử dụng nó - đọc dữ liệu không được cam kết có thể hơi khó hiểu một chút.


1
Sẽ thật tuyệt nếu bạn đề cập đến thực tế là SQL Server 2005 có phiên bản hàng nên nolocks thậm chí không còn cần thiết nữa.
Jonathan Allen

Chà, "với (nolock)" vẫn có chỗ đứng ngay cả trong SQL Server 2005 - nhưng lợi ích ngày càng mỏng hơn, đó là sự thật.
marc_s

18

Một trường hợp khác thường không ổn là trong cơ sở dữ liệu báo cáo, nơi dữ liệu có lẽ đã cũ và việc ghi chỉ không xảy ra. Tuy nhiên, trong trường hợp này, tùy chọn nên được quản trị viên đặt ở cấp cơ sở dữ liệu hoặc bảng bằng cách thay đổi mức cô lập mặc định.

Trong trường hợp tổng quát: bạn có thể sử dụng nó khi bạn đang rất chắc chắn rằng nó không quan trọng để đọc dữ liệu cũ. Điều quan trọng cần nhớ là rất dễ mắc sai lầm đó . Ví dụ: ngay cả khi bạn viết truy vấn ổn, bạn có chắc chắn sẽ có gì đó không thay đổi trong cơ sở dữ liệu trong tương lai để làm cho các cập nhật này quan trọng hơn không?

Tôi cũng sẽ thứ 2 khái niệm rằng nó có thể không phải là một ý tưởng tốt trong ứng dụng ngân hàng. Hoặc ứng dụng kiểm kê. Hoặc bất cứ nơi nào bạn nghĩ về giao dịch.


4
Là một người làm việc trên các ứng dụng ngân hàng, tôi phải nói rằng không có khóa không phải là vấn đề. Các bản ghi giao dịch, đó là các hàng được chèn nhưng không bao giờ được cập nhật hoặc xóa, có khả năng chống lại các vấn đề về đọc dữ liệu không được khuyến khích.
Jonathan Allen

15

Câu trả lời đơn giản - bất cứ khi nào SQL của bạn không thay đổi dữ liệu và bạn có một truy vấn có thể can thiệp vào hoạt động khác (thông qua khóa).

Rất đáng để xem xét cho bất kỳ truy vấn nào được sử dụng cho báo cáo, đặc biệt nếu truy vấn mất nhiều hơn 1 giây.

Nó đặc biệt hữu ích nếu bạn có các báo cáo kiểu OLAP mà bạn đang chạy với cơ sở dữ liệu OLTP.

Tuy nhiên, câu hỏi đầu tiên là "tại sao tôi lại lo lắng về điều này?" Theo kinh nghiệm của tôi, việc làm mờ hành vi khóa mặc định thường diễn ra khi ai đó ở chế độ "thử bất cứ thứ gì" và đây là một trường hợp mà hậu quả không mong muốn là không thể xảy ra. Thông thường, đó là trường hợp tối ưu hóa sớm và có thể dễ dàng bị nhúng trái vào một ứng dụng "chỉ trong trường hợp". Điều quan trọng là phải hiểu lý do tại sao bạn làm việc đó, vấn đề gì nó giải quyết và liệu bạn có thực sự có vấn đề hay không.


11

Câu trả lời ngắn:

Chỉ sử dụng WITH (NOLOCK)trong câu lệnh CHỌN trên các bảng có chỉ mục được nhóm.

Câu trả lời dài:

VỚI (NOLOCK) thường được khai thác như một cách kỳ diệu để tăng tốc độ đọc cơ sở dữ liệu.

Tập kết quả có thể chứa các hàng chưa được cam kết, thường được khôi phục sau đó.

Nếu VỚI (NOLOCK) được áp dụng cho bảng có chỉ mục không được nhóm thì chỉ mục hàng có thể được thay đổi bởi các giao dịch khác khi dữ liệu hàng đang được truyền vào bảng kết quả. Điều này có nghĩa là tập kết quả có thể thiếu các hàng hoặc hiển thị cùng một hàng nhiều lần.

ĐỌC CAM KẾT thêm một vấn đề bổ sung trong đó dữ liệu bị hỏng trong một cột trong đó nhiều người dùng thay đổi cùng một ô.


2
Đọc dữ liệu không được cam kết là chấp nhận được nếu nó không thay đổi quyết định cuối cùng. Ví dụ: nếu bạn đang cố gắng dự tính số tiền mà cửa hàng bán lẻ của bạn sẽ kiếm được trong 6 tháng tới, thì việc Tammy mua 2 cuộn khăn giấy khi cô ấy thực sự mua 3 sẽ không thay đổi quan điểm của bạn về tương lai .
Jonathan Allen

1
Nếu bộ lọc của bạn bao gồm ngay bây giờ, dữ liệu của bạn sẽ không chính xác ngay khi bạn chạy truy vấn. Nếu bộ lọc của bạn chỉ bao gồm dữ liệu lịch sử, việc sử dụng READ UNCOMITTED sẽ không ảnh hưởng đến nó. Có một lý do tại sao nó được bao gồm trong tiêu chuẩn ANSI.
Jonathan Allen

2
Không bao giờ nói không bao giờ. Nếu bạn CẦN dữ liệu chính xác 100%, thì bạn không nên sử dụng nolock. Đối với tôi, điều này thường không phải là trường hợp. Khi trình bày dữ liệu cho người dùng, vào thời điểm họ hành động trên dữ liệu, dù sao thì nó cũng có thể đã thay đổi, nhưng rất có thể là không, và sự tranh chấp khóa không đáng để trì hoãn phản hồi.
Perposterer

Hãy gắn bó với các hệ thống xứng đáng tồn tại. Đừng quên rằng Tammy có bộ não hoàn hảo, vì vậy, để sử dụng cơ sở dữ liệu để ghi lại các giao dịch mua khăn giấy nhỏ mà không ai có bất kỳ thông báo nào là tốt nhất. Trọng tâm của chúng tôi là các hệ thống thực sự quan trọng, ví dụ như mọi người được trả tiền đúng hạn, ứng phó với các trường hợp khẩn cấp, v.v ... Điều có lợi đáng kể là việc sử dụng VỚI (NOLOCK) được hiểu bởi những người lập trình bất kỳ hệ thống nào xứng đáng tồn tại. Khi một người có thể làm một công việc tốt hơn cơ sở dữ liệu thì hãy xem xét việc tái sử dụng các tài nguyên đó.
WonderWorker

10

2 xu của tôi - thật hợp lý khi sử dụng WITH (NOLOCK) khi bạn cần tạo báo cáo. Tại thời điểm này, dữ liệu sẽ không thay đổi nhiều và bạn sẽ không muốn khóa các hồ sơ đó.


2
Tôi nghĩ VỚI (NoLOCK) sẽ tốt hơn nếu bạn không quan tâm đến những thay đổi hiện tại.
Abdul Saboor

9

Nếu bạn đang xử lý các giao dịch tài chính thì bạn sẽ không bao giờ muốn sử dụng nolock. nolockđược sử dụng tốt nhất để chọn từ các bảng lớn có nhiều cập nhật và bạn không quan tâm nếu bản ghi bạn nhận được có thể bị lỗi thời.

Đối với hồ sơ tài chính (và hầu hết tất cả các hồ sơ khác trong hầu hết các ứng dụng) nolocksẽ tàn phá vì bạn có thể đọc dữ liệu từ một bản ghi được ghi và không nhận được dữ liệu chính xác.


5
Đáng ngạc nhiên, khi làm việc với dữ liệu tài chính, đây không phải là một vấn đề. Vì các hàng không bao giờ được chỉnh sửa và các tài khoản được đối chiếu vào cuối ngày, nên việc đọc dữ liệu không có thật tạm thời không làm gì cả.
Jonathan Allen

8

Tôi đã từng lấy "đợt tiếp theo" cho những việc cần làm. Trong trường hợp này không có vấn đề gì chính xác và tôi có rất nhiều người dùng đang chạy cùng một truy vấn này.


1
Chúng tôi làm một cái gì đó tương tự để trình bày một nhiệm vụ nền với một hàng công việc phải làm. Nếu, khi nó đến một bản ghi cụ thể, nó không còn tồn tại / phù hợp với tiêu chí lựa chọn, nó chỉ chuyển sang tiếp theo.
TripeHound

7

Sử dụng nolock khi bạn thấy ổn với dữ liệu "bẩn". Điều đó có nghĩa là nolock cũng có thể đọc dữ liệu đang trong quá trình sửa đổi và / hoặc dữ liệu không được cam kết.

Nói chung, không nên sử dụng nó trong môi trường giao dịch cao và đó là lý do tại sao nó không phải là một tùy chọn mặc định cho truy vấn.


3
Thời gian duy nhất bạn cần là trong một môi trường giao dịch cao. Nếu các bảng của bạn chủ yếu là không hoạt động, thì bạn sẽ không đạt được bất cứ điều gì bởi nó.
Jonathan Allen

7

Tôi sử dụng với gợi ý (nolock) đặc biệt trong cơ sở dữ liệu SQLServer 2000 có hoạt động cao. Tôi không chắc chắn rằng nó là cần thiết trong SQL Server 2005 tuy nhiên. Gần đây tôi đã thêm gợi ý đó trong SQL Server 2000 theo yêu cầu của DBA của khách hàng, vì anh ta nhận thấy rất nhiều khóa bản ghi SPID.

Tất cả những gì tôi có thể nói là việc sử dụng gợi ý KHÔNG làm tổn thương chúng tôi và dường như đã làm cho vấn đề khóa tự giải quyết. DBA tại khách hàng cụ thể đó về cơ bản khẳng định rằng chúng tôi sử dụng gợi ý.

Nhân tiện, các cơ sở dữ liệu mà tôi xử lý là các bản sao lưu cho các hệ thống khiếu nại y tế của doanh nghiệp, vì vậy chúng tôi đang nói về hàng triệu hồ sơ và hơn 20 bảng trong nhiều lần tham gia. Tôi thường thêm một gợi ý VỚI (nolock) cho mỗi bảng trong phép nối (trừ khi đó là bảng dẫn xuất, trong trường hợp đó bạn không thể sử dụng gợi ý cụ thể đó)


1
SQL Server 2005 đã thêm "phiên bản hàng" sẽ giúp giảm đáng kể nhu cầu về nolocks. Gần đây chúng tôi đã nâng cấp và không đào tạo các DBA của mình để ngừng sử dụng chúng.
Jonathan Allen

5

Câu trả lời đơn giản nhất là một câu hỏi đơn giản - bạn có cần kết quả của mình để được lặp lại không? Nếu có thì NOLOCKS không phù hợp trong mọi trường hợp

Nếu bạn không cần lặp lại thì nolocks có thể hữu ích, đặc biệt nếu bạn không có quyền kiểm soát tất cả các quy trình kết nối với cơ sở dữ liệu đích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.