Sẽ tăng độ trễ mạng gây ra khóa bảng trong MS SQL Server?


16

Nếu tôi đang thực hiện một cuộc gọi đến cơ sở dữ liệu SQL Server qua mạng có độ trễ cao, liệu khóa bảng có xảy ra do độ trễ đó không? Giả sử tôi truy vấn bảng A đối với một số bản ghi và SQL Server phải trả lại dữ liệu đó qua mạng chậm - sẽ có khóa đọc trên bảng A trong khi máy chủ gửi phản hồi qua mạng hoặc SQL Server sẽ giải phóng khóa trước khi gửi Phản hồi?

Ngoài ra, câu trả lời sẽ thay đổi dựa trên kích thước của câu trả lời? Nếu nó chỉ phải trả lại vài KB so với vài trăm MB, điều đó có làm nên sự khác biệt không?

Tạo một giao dịch rõ ràng, chạy các truy vấn và đóng giao dịch rõ ràng sẽ khiến các bảng bị khóa, vì thời lượng của giao dịch có tương quan với độ trễ của tôi.


Trừ khi bạn chỉ định một nolockgợi ý, sẽ luôn có một khóa . Độ trễ chỉ xác định thời gian khóa sẽ được giữ.
Brandon

3
Và ngay cả với nolock, bạn vẫn sẽ nhận được khóa
billinkc

@brandon Điều đó có được Microsoft ghi lại ở bất cứ đâu không? Các tìm kiếm của tôi đã trở nên trống rỗng.
Evan M

1
@Brandon NOLOCK không có nghĩa là bạn nghĩ gì.
Aaron Bertrand

3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- điều này ngụ ý nếu bạn sử dụng nolock thì có thể không có khóa. Tôi chỉ đơn thuần là làm rõ.
Aaron Bertrand

Câu trả lời:


15

Nếu máy khách mất nhiều thời gian để nhận dữ liệu và lần lượt gửi xác nhận đến SQL Server rằng nó đã nhận được dữ liệu SQL Server phải chờ, do chờ đợi này, SQL Server sẽ không giải phóng các khóa được giữ bởi truy vấn trừ khi nhận được xác nhận từ máy khách.

Điều này là không chính xác, nó phụ thuộc vào mức độ cô lập.

Tại các READ COMMITTEDkhóa mặc định không được giữ trong suốt thời gian thực hiện câu lệnh. READ COMMITTEDkhông cung cấp tính nhất quán đọc mức độ tuyên bố, bảo đảm duy nhất là bạn không thể đọc dữ liệu không được cam kết. Một khóa chia sẻ được mua và giữ để đọc hàng và sau đó phát hành.

Trừ khi bạn có các loại LOB.

Các loại LOB, có khả năng rất lớn, không thể được đệm. Một khóa chia sẻ phải được mua và giữ cho đến khi câu lệnh hoàn thành, về cơ bản mang lại cho bạn REPEATABLE READhành vi tại READ COMMITTED.

Nếu tôi đang thực hiện một cuộc gọi đến cơ sở dữ liệu MSSQL qua mạng có độ trễ cao, liệu khóa bảng có xảy ra do độ trễ đó không?

Độ trễ không gây ra khóa bảng, không. Tuy nhiên, nếu khóa bảng đã được mua, độ trễ sẽ kéo dài nó.

Để trích dẫn ai đó biết cơ chế này tốt hơn tôi ( @RemusRusanu ):

Kết quả được trả về chương trình máy khách khi tiến hành thực hiện. Khi các hàng 'bong bóng' lên cây thực thi, toán tử trên cùng thường được giao nhiệm vụ ghi các hàng này vào bộ đệm mạng và gửi chúng trở lại máy khách. Kết quả không được tạo trước tiên vào một số bộ lưu trữ trung gian (bộ nhớ hoặc đĩa) và sau đó được gửi lại cho máy khách, thay vào đó nó được gửi lại như đang được tạo (khi truy vấn thực thi). Gửi kết quả trở lại máy khách, tất nhiên, phải tuân theo giao thức kiểm soát luồng mạng. Nếu máy khách không chủ động tiêu thụ kết quả (ví dụ: bằng cách gọi SqlDataReader.Read ()) thì cuối cùng, điều khiển luồng sẽ phải chặn phía gửi (truy vấn đang được thực thi) và đến lượt nó sẽ tạm dừng việc thực thi truy vấn.[nguồn]

Trường hợp kết quả không được tiêu thụ nhanh như SQL Server có thể phân phối chúng, do máy khách hoặc mạng, chúng tôi thấy sự ASYNC_NETWORK_IOchờ đợi tích lũy. Để nhắc lại, điều này sẽ không ảnh hưởng đến các khóa được mua, chỉ là thời lượng chúng được giữ.


9

Câu trả lời của Mark đã xóa tan rất nhiều sự nhầm lẫn của tôi, nhưng tôi muốn đăng những phát hiện của mình sau khi tôi thử nghiệm điều này bằng NetBalancer để mô phỏng độ trễ.

Tôi đã có máy cục bộ của mình gọi một máy chủ SQL từ xa và thực thi cả CHỌN và CHỌN trên một bảng trong một giao dịch nhỏ. Trên máy từ xa, tôi đã kết nối với phiên bản SQL cục bộ và sử dụng vòng lặp WHILE để lặp lại nhiều lần trên bảng sys.dm_tran_locks, tìm kiếm bất kỳ khóa nào trên bảng mà tôi đang sửa đổi và đọc từ đó. Tôi đã cài đặt NetBalancer trên máy chủ và sử dụng nó để mô phỏng độ trễ mạng trên kết nối mạng của máy chủ.

Đây là những gì tôi tìm thấy:

  • Đối với các câu lệnh không trả lại nhiều dữ liệu cho khách hàng, độ trễ không ảnh hưởng đến việc khóa. Tôi chỉ trả lại vài trăm byte dữ liệu. Giao dịch trên máy của tôi có WAITFOR 250ms giữ khóa và khi tôi tăng độ trễ mạng lên 5000ms thì thời lượng khóa ở mức gần 250ms.
  • Đối với các báo cáo trả lại nhiều dữ liệu, độ trễ chắc chắn ảnh hưởng đến việc khóa Tôi đã trả lại hàng chục nghìn hàng cho khách hàng và không có độ trễ, thời gian khóa là ngắn. Khi tôi tăng độ trễ, các khóa tiếp tục cho đến khi tôi nhận được tất cả dữ liệu.

Từ điều này, tôi kết luận rằng độ trễ không quan trọng miễn là dữ liệu phù hợp với bộ đệm mạng. Nếu SQL phải đặt nhiều dữ liệu vào bộ đệm mạng, độ trễ sẽ khiến bộ đệm đó sao lưu và SQL sẽ giữ các khóa bảng cho đến khi nó có thể đặt tất cả kết quả truy vấn vào bộ đệm.


Kết quả thú vị. Chương trình khách hàng / thư viện này là gì với?
James L

Đồ tốt. Bất kỳ cơ hội nào bạn có thể dành thêm một chút thời gian cho việc này và xem liệu bạn có thể xác định kích thước kết quả mà điều này xảy ra không?
Mark Storey-Smith

@ MarkStorey-Smith Tôi không nghĩ mình có thể nhận được một giá trị chính xác và chắc chắn nó sẽ thay đổi theo máy. Từ vircom.com/security/improve-sql-nic-performance , có vẻ như đó là cài đặt trên NIC cục bộ của bạn và cài đặt trên máy chủ cơ sở dữ liệu của tôi được đặt thành 'tự động'
Evan M

@James Tôi chỉ sử dụng SSMS trên cả hai máy
Evan M

0

Nếu tôi đang thực hiện một cuộc gọi đến cơ sở dữ liệu MSSQL qua mạng có độ trễ cao, liệu khóa bảng có xảy ra do độ trễ đó không?

Khi SQL Server được kích hoạt và hoàn thành một truy vấn, nó sẽ tạo ra các kết quả, đặt nó vào bộ đệm đầu ra và gửi nó đến máy khách, sau đó lấy kết quả từ bộ đệm đầu ra. SQL Server sẽ không giải phóng các khóa được giữ bởi truy vấn trừ khi nhận được Xác nhận từ Máy khách. Mà có thể gây ra chặn.

Chỉnh sửa: Evan bạn có thể tham khảo bài viết hỗ trợ MS này

Trong phần 3

Chặn gây ra bởi một SPID mà ứng dụng khách tương ứng không tải tất cả các hàng kết quả để hoàn thành

Sau khi gửi truy vấn đến máy chủ, tất cả các ứng dụng phải ngay lập tức tìm nạp tất cả các hàng kết quả để hoàn thành. Nếu một ứng dụng không tìm nạp tất cả các hàng kết quả, khóa có thể được để lại trên các bảng, chặn người dùng khác. Nếu bạn đang sử dụng một ứng dụng gửi các câu lệnh SQL trong suốt đến máy chủ, ứng dụng phải tìm nạp tất cả các hàng kết quả. Nếu nó không (và nếu nó không thể được cấu hình để làm như vậy), bạn có thể không thể giải quyết vấn đề chặn. Để tránh sự cố, bạn có thể hạn chế các ứng dụng hoạt động kém vào cơ sở dữ liệu báo cáo hoặc hỗ trợ quyết định.


Cảm ơn câu trả lời của bạn Shanky! Bạn có tình cờ biết nếu điều này được ghi lại ở bất cứ đâu?
Evan M


5
Điều này LAF không đúng.
Mark Storey-Smith

Điều này đúng, có vẻ như ứng dụng không tìm nạp tất cả các hàng kết quả, các khóa có thể được để lại trên các bảng, chặn người dùng khác. Nếu bạn đang sử dụng một ứng dụng gửi các câu lệnh SQL trong suốt đến máy chủ, ứng dụng phải tìm nạp tất cả các hàng kết quả. Nếu nó không (và nếu nó không thể được cấu hình để làm như vậy), bạn có thể không thể giải quyết vấn đề chặn. Để tránh sự cố, bạn có thể hạn chế các ứng dụng hoạt động kém vào cơ sở dữ liệu báo cáo hoặc hỗ trợ quyết định. ' Hơn tôi đã nói về các điều khoản chung. Bạn có thể đọc từ đây support2.microsoft.com/kb/224453
Shanky

4
@Shanky Tạo một bảng lớn. SELECT *từ nó trong READ COMMITTEDmột kết nối SSMS, giám sát các khóa từ một kết nối khác. Bất cứ lúc nào, bạn thấy có bao nhiêu ổ khóa?
Mark Storey-Smith
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.