Lợi ích của CẤP PHÂN TÍCH GIAO DỊCH GIAO DỊCH ĐỌC HIỂU


12

Tôi sử dụng SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDtrong phần lớn các truy vấn SQL chung của mình, chủ yếu là vì điều này đã được khoan vào tôi khi ban đầu học ngôn ngữ.

Theo hiểu biết của tôi, mức độ cô lập này hoạt động theo cách tương tự mà WITH (NO LOCK)tôi chỉ có xu hướng sử dụng SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

  • Có bao giờ tôi nên sử dụng WITH (NO LOCK)hơn SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
  • SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDngăn người dùng khác bị khóa khỏi các bảng mà tôi đang đọc không?
  • Nếu SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDđược sử dụng để dừng khóa, nhưng tôi chỉ đọc dữ liệu, điểm quan trọng trong việc sử dụng nó là gì? Có phải chỉ các hệ thống truy vấn chuyên sâu sẽ tạo ra các khóa? Có đáng để sử dụng nó khi chạy các truy vấn sẽ trả về trong 5-10 giây không?
  • Tôi đã nói không sử dụng SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDkhi đọc dữ liệu sẽ được sử dụng trong các bản cập nhật, có lẽ để tránh cập nhật dữ liệu bẩn. Đây sẽ là lý do duy nhất?
  • Với loại cơ sở dữ liệu mà tôi đang làm việc, có một môi trường sản xuất và thử nghiệm. Chúng tôi sẽ rất hiếm khi truy vấn môi trường sản xuất nhưng khi tôi cần, tôi thường sẽ sử dụng SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDtrong truy vấn của mình. Tôi hiểu rằng đọc bẩn là có thể với điều này. Ngoài việc nhận lại dữ liệu mà cuối cùng có thể không được cam kết với cơ sở dữ liệu (và do đó ném kết quả của tôi ra) những loại 'đọc bẩn' nào khác có thể có thể?

Xin lỗi cho các câu hỏi đại chúng.


2
Bạn có thể đọc cùng một dữ liệu hai lần là một hố khác. Sử dụng RU hoặc NO LOCK làm tiêu chuẩn là một ý tưởng tồi.
James Anderson

9
Tôi sẽ không sử dụng READ UNCOMMITTEDở khắp mọi nơi, trong cùng một cách chính xác như tôi sẽ không sử dụng WITH (NOLOCK)ở khắp mọi nơi (họ cơ bản là điều tương tự) blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere
Đánh dấu Sinkinson

1
Nhìn vào các mô hình cách ly SNAPSHOT. Chúng mạnh hơn RCU rất nhiều và cũng không chặn hoặc gây ra chặn. Chúng có vẻ như là một mô hình mặc định tốt cho bạn (thay vì mặc định là RCU!).
usr

Câu trả lời:


25

Thật là tồi tệ, rằng bạn đã học nó theo cách đó (xin lỗi!).

READ UNCOMMITTEDHãy để bạn đọc từng hàng, vâng. Ngay cả những người hiện đang sử dụng trong một INSERT, UPDATE, DELETEhoạt động. Điều này rất hữu ích nếu bạn cần xem nhanh một số Dữ liệu hoặc trong các nhiệm vụ quan trọng - Các SELECThoạt động trong đó một khối sẽ rất có hại.

Trong thực tế, bạn có nguy cơ tính toàn vẹn của bạn. Nó có thể xảy ra rằng bạn đọc một hàng, hiện đang được sử dụng để bị xóa hoặc thay đổi. Nó cũng có thể xuất hiện rằng bạn đọc một giá trị sai. Điều này có thể thực sự không phổ biến, nhưng nó có thể xảy ra. Tôi có ý gì với điều đó? Chà, hãy nghĩ về một hàng rất rộng (nó có nhiều cột với nhiều cột dài nvarchar). Một bản cập nhật xảy ra trên hàng này và đặt các giá trị mới. Trong những trường hợp hiếm hoi, điều đó có thể xảy ra với bạn, rằng bạn chỉ đọc được một nửa hàng. Một điều khác có thể xảy ra, ví dụ, nếu người dùng thay đổi giá trị đăng nhập của mình. Anh ta thay đổi mail + mật khẩu. Thư đã được đặt, nhưng mật khẩu thì không. Bằng cách này bạn có một trạng thái không nhất quán.

Tôi sẽ đề nghị để quên về READ UNCOMMITTED. Chỉ cần sử dụng nó khi thực sự cần thiết.

Một cách khác để bạn có thể kích hoạt READ_COMMITTED_SNAPSHOTtùy chọn cơ sở dữ liệu - do đó bạn có thể sử dụng READ COMMITTED SNAPSHOTdo phiên bản hàng được bật trong tempdb của bạn. Bằng cách này bạn chỉ cần đọc một phiên bản khác (cũ hơn) của một hàng. Điều này sẽ không chặn Truy vấn của bạn. Nhưng nó có thể xảy ra rằng bạn cũng đọc một giá trị cũ, nhưng một giá trị cũ nhất quán.

Một ý tưởng khác có thể được WITH(READPAST)thay thế WITH(NOLOCK). Bạn sẽ đọc trạng thái cũ của bảng (hơi giống trong SNAPSHOT ISOLATION), nhưng thay vào đó bạn sẽ bỏ qua tất cả các hàng bị khóa.


@Ionic, cảm ơn bạn rất nhiều vì đã phản hồi! Tôi thực sự đánh giá cao sự giúp đỡ về điều đó.
dmoney

@HingeSight, nghe có vẻ như vậy, nhưng rất có khả năng đó là cách giải thích của tôi về tuyên bố, nhờ một trong hai cách cho đầu vào của bạn.
dmoney

1
SNAPSHOT ISOLATIONkhông cần bật để bật READ COMMITTED SNAPSHOT. Chỉ có READ COMMITTED SNAPSHOTtùy chọn cơ sở dữ liệu cần được bật để phiên bản hàng thay vì khóa để đọc tính nhất quán, tránh sự cần thiết phải đọc bẩn.
Dan Guzman

Vâng, tôi có nghĩa là @DanGuzman. Xin lỗi câu trả lời là một chút không rõ ràng trong điểm đó. Tôi đã chỉnh sửa nó. :-)
Ionic

Với READPAST, bạn sẽ bỏ qua các bản ghi bị khóa, bạn sẽ không nhận được các giá trị cũ - vì vậy nơi duy nhất tôi đã tìm ra nó có thể được sử dụng là xử lý hàng đợi
James Z

2

Như câu trả lời được chấp nhận, hãy quên sử dụng mức cô lập READ UNCOMMITTED (trừ khi thực sự cần thiết) vì bạn có nguy cơ đọc sai dữ liệu. Nhưng để trả lời gạch đầu dòng thứ 3 trong câu hỏi của bạn, có hai tình huống tôi thấy hữu ích:

  1. Khi viết và kiểm tra các gói SSIS của SQL Server, các bước của gói có thể được gói trong một giao dịch. Nếu bạn đang kiểm tra gói bằng cách chạy từng bước trong trình gỡ lỗi SSIS, bạn có thể muốn kiểm tra các bảng trong khi có các khóa trên bảng. Sử dụng SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED cho phép bạn sử dụng SQL Server Manager Studio để kiểm tra các bảng trong khi gói đang được gỡ lỗi.

  2. Trong SQL Server Manager Studio, bạn có thể muốn kiểm tra mã T-SQL bằng cách gói nó trong một giao dịch để cung cấp cho bạn tùy chọn khôi phục các thay đổi. Ví dụ: trên cơ sở dữ liệu kiểm tra, bạn có thể muốn khôi phục dữ liệu về trạng thái ban đầu như một phần của kiểm tra. Nếu bạn đang kiểm tra mã được bọc giao dịch và bạn muốn kiểm tra các bảng bị khóa trong khi giao dịch đang được tiến hành, bạn có thể sử dụng THIẾT LẬP CẤP PHÂN TÍCH GIAO DỊCH ĐỌC HIỂU để kiểm tra các giá trị trong một cửa sổ khác.

Tôi chấp nhận đây là những cách sử dụng khá mơ hồ cho READ UNCOMMITTED, nhưng tôi đã thấy chúng hữu ích trong môi trường thử nghiệm.


1

Trong hầu hết các cơ sở dữ liệu, phần lớn các hoạt động, thậm chí chèn, xóa và cập nhật, nằm ngoài các giao dịch rõ ràng.

Chắc chắn, READ UNCOMMITTED(Dirty Reads) có thể cung cấp thông tin không chính xác trong những trường hợp này, nhưng thông tin đó đã đúng 5 giây trước đó.

Thời điểm mà Dirty Reads tạo ra kết quả thực sự tồi tệ là khi Giao dịch thất bại và phải được khôi phục hoặc khi chạy truy vấn đối với hai bảng thường được cập nhật cùng nhau bằng giao dịch rõ ràng.

Trong khi đó, trên một cơ sở dữ liệu lớn, bận rộn điển hình có tỷ lệ đọc (ghi) từ 100 trở lên đến 1, MỌI truy vấn (đọc) không sử dụng Dirty Reads đang làm chậm hệ thống vì cần phải lấy và kiểm tra đối với các khóa VÀ nó làm cho nhiều khả năng các giao dịch sẽ thất bại (thường là do Deadlocks) có thể gây ra các vấn đề toàn vẹn cơ sở dữ liệu nghiêm trọng hơn.

Thay vào đó, việc sử dụng đọc bẩn làm cho hệ thống NHIỀU nhanh hơn và đáng tin cậy hơn (một phần do hiệu suất được cải thiện làm cho sự không nhất quán ít có khả năng xảy ra).

Chắc chắn, có những lúc chúng không nên được sử dụng. Tôi không thích đặt cơ sở dữ liệu thành mặc định để sử dụng READ UNCOMMITTEDmức cô lập hoặc thậm chí sử dụng SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDcâu lệnh rõ ràng khi bắt đầu SQL Script và SP - có quá nhiều khả năng rằng Dirty Read sẽ xảy ra khi không nên. Thay vào đó, các (NOLOCK)gợi ý là một cách tiếp cận tốt hơn nhiều vì chúng chỉ ra rõ ràng rằng lập trình viên nghĩ về những gì họ đang làm và quyết định rằng, đối với bảng cụ thể này trong truy vấn cụ thể này, Dirty Reads an toàn.

Nếu bạn đang lập trình một ứng dụng để chuyển tiền từ tài khoản ngân hàng này sang tài khoản ngân hàng khác, bạn không nên sử dụng Dirty Reads. Nhưng hầu hết các ứng dụng không cần mức độ hoang tưởng đó.

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.