2012-08-06 41 views
7

Tôi có một truy vấn chọn phức tạp và một bảng lớn.Máy chủ SQL - thực hiện [SELECT] khóa [CẬP NHẬT]?

Tôi đang chạy tuyên bố này select, trong khi đó tuyên bố Update đến và cố gắng cập nhật bảng.

IMHO - cập nhật yêu cầu khóa độc quyền - vì vậy báo cáo cập nhật sẽ phải chờ cho đến khi lệnh chọn hoàn tất.

  1. Tôi có đúng không?

  2. gì tôi có thể làm để: thực hiện phức tạp select, cũng cho phép chạy update lệnh (hiện tôi không quan tâm về dữ liệu bẩn)

+1

Bạn đang nói về mức cô lập giao dịch nào? – Oded

+0

@Oded Mặc định - Tôi tin rằng nó đã được đọc. –

+3

* "hiện tại tôi không quan tâm đến dữ liệu bẩn" *: hãy cẩn thận [những gì bạn mong muốn] (http://blogs.msdn.com/b/sqlcat/archive/2007/02/01/previously-committed- rows-might-be-miss-if-nolock-hint-is-used.aspx). –

Trả lời

13

Có - để một mức độ.

bao lâu một SELECT giữ vào một khóa chia sẻ là tùy thuộc vào mức độ cô lập của giao dịch:

  • READ UNCOMMITTED - không khóa chia sẻ được mua ở tất cả - UPDATE không bị chặn
  • READ COMMITTED - chia sẻ khóa chỉ được mua trong thời gian đọc dữ liệu - UPDATE có thể bị chặn trong một khoảng thời gian rất ngắn
  • REPEATABLE READSERIALIZABLE - khóa chia sẻ được mua và giữ trên đó l khi kết thúc giao dịch - UPDATE bị chặn cho đến khi giao dịch SELECT kết thúc

Về mặt kỹ thuật, báo cáo kết quả UPDATE đầu tiên nhận được một khóa UPDATE - đó là tương thích với một khóa chia sẻ (như được sử dụng bởi các SELECT) - trong suốt thời gian thời gian trong khi nó đang đọc các giá trị hiện tại của các hàng được cập nhật.

Khi đã xong, khóa Update sẽ được chuyển sang khóa độc quyền để dữ liệu mới được ghi vào bảng.

+0

'câu lệnh UPDATE đầu tiên nhận được khóa UPDATE - tương thích với khóa chia sẻ 'Tôi không hiểu marc. bản cập nhật đang chờ để chọn kết thúc? –

+1

@RoyiNamir: bản cập nhật có thể lấy khóa 'Update' (để đọc dữ liệu" cũ ") trong khi một quá trình khác vẫn đọc cùng hàng đó và có khóa' shared' trên hàng đó. Bản cập nhật sẽ không thể đi đến một khóa độc quyền (để ghi lại dữ liệu "mới"), tuy nhiên, miễn là khóa 'shared' vẫn còn đúng chỗ - vì vậy nó sẽ phải đợi ở đó ... –

5

Khi bạn chạy hai câu lệnh đồng thời (một SELECT và UPDATE), hành vi thực tế sẽ cơ bản là ngẫu nhiên. Điều này là do không phải thao tác nào là tức thời. Để đơn giản hóa, hãy xem xét bảng của bạn một danh sách và SELECT đang duyệt qua danh sách này, nhìn vào một hàng tại một thời điểm. CẬP NHẬT cũng đang cố cập nhật một hoặc nhiều hàng. Khi UPDATE đang cố gắng cập nhật một hàng đằng sau lệnh SELECT thì không có gì xảy ra (không chặn) vì SELECT đã tiến triển qua điểm UPDATE. Nếu CẬP NHẬT đang cố gắng cập nhật hàng mà tại đó SELECT đang tìm kiếm ngay bây giờ thì UPDATE sẽ phải chờ SELECT để tiếp tục, điều này sẽ diễn ra rất rất nhanh và UPDATE sẽ bỏ chặn và thành công, trong khi SELECT đang tiến lên phía trước. Nhưng nếu UPDATE đang cập nhật một hàng trước của CHỌN thì bản cập nhật sẽ thành công và, sau, SELECT cuối cùng sẽ đạt được chính xác hàng này và sẽ dừng lại, bị chặn.Bây giờ, SELECT phải đợi cho đến khi giao dịch đã thực hiện UPDATE cam kết.

Đây là câu chuyện được đơn giản hóa. Cuộc sống thực tế phức tạp hơn nhiều. SELECT có thể có nhiều điểm đọc (kế hoạch song song). Cả SELECT và UPDATE đều có thể chọn một đường dẫn truy cập, có nghĩa là sử dụng một hoặc nhiều chỉ mục phụ để định vị các hàng. Truy vấn phức tạp có thể chứa các toán tử gây ra nhiều lần tra cứu vào một bảng (ví dụ: các phép nối). Cả SELECT và UPDATE đều có thể thực hiện tra cứu bookmark để tìm nạp dữ liệu BLOB, thay đổi đáng kể hành vi khóa. Ước tính Cardinality có thể khiến cho SELECT chạy ở chế độ khóa chi tiết cao (ví dụ: khóa chia sẻ mức bảng). CẬP NHẬT có thể kích hoạt khóa leo thang và sự leo thang có thể thất bại hoặc thành công. Choosing different access paths can lead to deadlock. False lock contention can occur due to hash collisions. Chỉ có khoảng một vô số các biến có tiếng nói trong này. Và tôi thậm chí không đề cập đến mức cô lập cao hơn (đọc lặp lại, có thể tuần tự hóa).

Có lẽ bạn nên sử dụng cách ly SNAPSHOT và ngừng lo lắng về vấn đề này?

+0

Nếu bạn đề nghị đi với 'SNAPSHOT' - hãy chắc chắn rằng' TempDB' được thiết lập đúng! (vị trí và số lượng tệp dữ liệu, tùy chọn định kích thước, v.v.) –

+1

Có, lặp lại và có thể tuần tự hóa khiến khóa chia sẻ được giữ lại cho phạm vi giao dịch. Serializable cũng có thể thêm nhiều khóa. Tất cả những điều này thêm phức tạp. –

+1

@marc_s: liên kết đến chủ đề MSDN bao gồm [Cách sử dụng tài nguyên phiên bản hàng] (http://msdn.microsoft.com/en-us/library/ms175492 (v = sql.105)). Tôi không muốn dọa người dùng đi, vì tôi coi những lợi ích của SNAPSHOT vượt xa chi phí của nó. –

Các vấn đề liên quan