Trong 18 tháng qua, tôi đã tập trung vào phản ứng giật gân để chờ đợi phân tích thống kê và các chủ đề liên quan đến điều chỉnh hiệu suất khác và trong bài đăng này, tôi sẽ tiếp tục điều đó và thảo luận về PAGELATCH_XX chờ đợi. XX ở cuối thời gian chờ có nghĩa là có nhiều loại PAGELATCH chờ đợi, và các ví dụ phổ biến nhất là:
- PAGELATCH_SH - ( SH đang) chờ truy cập vào trang tệp dữ liệu trong bộ nhớ để có thể đọc nội dung trang
- PAGELATCH_EX hoặc PAGELATCH_UP - ( EX lừa dối hoặc LÊN ngày) đang chờ truy cập vào trang tệp dữ liệu trong bộ nhớ để có thể sửa đổi nội dung trang
Khi một trong những kiểu chờ này phổ biến nhất trên máy chủ, phản ứng giật gân là vấn đề xảy ra với I / O (tức là nhầm lẫn với PAGEIOLATCH_XX loại chờ đợi, mà tôi đã đề cập trong một bài đăng vào năm 2014) và ai đó cố gắng thêm bộ nhớ hoặc điều chỉnh hệ thống con I / O. Cả hai phản ứng này đều không có bất kỳ ảnh hưởng nào, vì các trang tệp dữ liệu đang tranh chấp đều đã có trong bộ nhớ trong vùng đệm!
Trong mọi trường hợp, bạn có thể xem liệu bạn có gặp sự cố với PAGELATCH_XX tranh chấp bằng cách sử dụng sys.dm_os_waiting_tasks trên blog của tôi hoặc sử dụng một công cụ như Trình tư vấn hiệu suất, như đã trình bày (cho một kiểu chờ khác) trong bài đăng này.
Vậy nguồn gốc của sự tranh cãi là gì? Trước tiên, tôi sẽ giải thích cơ sở đằng sau những kiểu chờ đợi này, sau đó tôi sẽ thảo luận về hai nguyên nhân phổ biến nhất của PAGELATCH_XX tranh chấp.
Bối cảnh:Các chốt
Trước khi tôi đi vào một số nguyên nhân của PAGELATCH_XX Chờ đã, tôi muốn giải thích tại sao chúng còn tồn tại.
Trong bất kỳ hệ thống đa luồng nào, cấu trúc dữ liệu có thể được truy cập và thao tác bởi nhiều luồng cần được bảo vệ để ngăn ngừa các trường hợp như:
- Hai chuỗi cập nhật cấu trúc dữ liệu đồng thời và một số cập nhật bị mất
- Một chuỗi cập nhật cấu trúc dữ liệu đồng thời với một chuỗi khác đang đọc cấu trúc dữ liệu, do đó, chuỗi đọc thấy hỗn hợp dữ liệu cũ và mới
Đây là khoa học máy tính cơ bản và SQL Server cũng không khác, vì vậy tất cả các cấu trúc dữ liệu bên trong SQL Server cần phải có kiểm soát truy cập đa luồng.
Một trong những cơ chế mà SQL Server sử dụng để thực hiện điều này được gọi là chốt, trong đó việc giữ chốt ở chế độ độc quyền sẽ ngăn các luồng khác truy cập vào cấu trúc dữ liệu và giữ chốt ở chế độ chia sẻ sẽ ngăn các luồng khác thay đổi cấu trúc dữ liệu. SQL Server cũng sử dụng spinlock cho một số cấu trúc dữ liệu và tôi đã thảo luận về những điều này trong bài đăng này vào năm 2014.
Nhưng tại sao một trang tệp dữ liệu trong bộ nhớ lại được bảo vệ bằng chốt, bạn có thể thắc mắc? Chà, một trang tệp dữ liệu chỉ là một cấu trúc dữ liệu, mặc dù là một mục đích đặc biệt, và do đó, cần có các điều khiển truy cập giống như bất kỳ cấu trúc dữ liệu nào khác. Vì vậy, khi một chuỗi cần sửa đổi trang tệp dữ liệu, chuỗi đó cần có được chốt cập nhật hoặc độc quyền trên trang và nếu không thể và cần đợi, hãy nhập loại đợi PAGELATCH_EX hoặc PAGELATCH_UP kết quả.
Nội dung tempdb cổ điển
PAGELATCH tranh chấp trong tempdb thường xảy ra trên bitmap cấp phát và xảy ra với khối lượng công việc có nhiều kết nối đồng thời tạo và thả các bảng tạm thời nhỏ (được lưu trữ trong tempdb).
Khi hàng đầu tiên được chèn vào bảng tạm thời, hai trang phải được phân bổ (một trang dữ liệu và một trang IAM, theo dõi trang dữ liệu). Các trang này cần được đánh dấu là được cấp phát trong một trang cấp phát đặc biệt được gọi là trang PFS và theo mặc định được cấp phát từ các phạm vi dữ liệu đặc biệt được theo dõi bởi một trang cấp phát khác được gọi là trang SGAM (có thể tìm thấy chi tiết về những điều này trong bài đăng blog cũ của tôi đây). Khi bảng tạm thời bị xóa, các trang này cần được phân bổ lại, cần có nhiều thay đổi hơn đối với các trang PFS và SGAM.
Nếu các bảng tạm thời nhỏ và kích thước tích lũy của tất cả các bảng tạm thời được tạo đồng thời nhỏ hơn 64MB, thì tất cả các thay đổi bitmap phân bổ này đều tập trung vào các trang PFS và SGAM đầu tiên trong tệp dữ liệu tempdb (với ID trang (1:1) và (1:3) tương ứng). Việc cập nhật một trong các trang phân bổ này yêu cầu phải chốt trang và mỗi lần chỉ có một chuỗi có thể thay đổi trang, vì vậy tất cả các chuỗi khác phải đợi - với kiểu đợi PAGELATCH_UP .
Từ SQL Server 2005 trở đi, các bảng tạm thời có thể được lưu vào bộ nhớ cache khi bị xóa, miễn là chúng có kích thước nhỏ hơn 8MB (và trong SQL Server 2014 không được tạo trong một quy trình được lưu trữ cũng có các câu lệnh DDL trên bảng tạm thời). Điều này có nghĩa là luồng tiếp theo thực hiện cùng một kế hoạch truy vấn có thể đưa bảng tạm thời ra khỏi bộ đệm và không phải xử lý các phân bổ ban đầu. Điều này làm giảm sự tranh cãi trên các bitmap phân bổ, nhưng bộ nhớ cache của bảng tạm thời không lớn lắm, vì vậy khối lượng công việc với hàng trăm lần tạo / giảm bảng tạm thời đồng thời sẽ vẫn có nhiều tranh cãi.
Việc ngăn chặn sự tranh cãi trên các trang SGAM trong tempdb bằng cách bật cờ theo dõi được lập thành tài liệu 1118 trên máy chủ, mà tôi cho là nên được bật trên tất cả các máy chủ trên toàn thế giới và thực sự là hành vi mặc định không thể thay đổi trong SQL Server 2016.
Việc ngăn chặn tranh chấp trên các trang PFS trong tempdb khó hơn một chút. Giả sử rằng các bảng tạm thời là cần thiết cho hiệu suất, thì mẹo là có nhiều tệp dữ liệu cho tempdb để việc phân bổ được thực hiện luân phiên giữa các tệp, sự tranh cãi được chia thành nhiều trang PFS và do đó tranh chấp tổng thể giảm xuống. Không có câu trả lời đúng cho số lượng tệp dữ liệu đáng tiếc bạn nên có. Bạn có thể đọc thêm về hướng dẫn được chấp nhận chung về vấn đề này trong bài viết KB 2154845 và trong bài đăng blog này.
Chèn điểm phát sóng
Trong cơ sở dữ liệu người dùng, nguyên nhân phổ biến dẫn đến số lượng PAGELATCH_EX cao đợi là một điểm phát sóng chèn.
Điều này có thể xảy ra khi một bảng có chỉ mục nhóm với khóa cụm int hoặc bigint và kích thước hàng đủ nhỏ để nhiều hàng chục hoặc nhiều hàng trong bảng có thể vừa với trang dữ liệu ở cấp độ lá của chỉ mục nhóm.
Đối với một bảng như vậy, nếu khối lượng công việc bao gồm nhiều hàng chục hoặc hàng trăm luồng đồng thời chèn vào bảng, nhiều luồng sẽ tạo ra các hàng có giá trị nhận dạng (và do đó là các khóa cụm) cần được chèn vào cùng một trang dữ liệu cấp lá .
Bây giờ, hãy nhớ rằng việc thực hiện bất kỳ thay đổi nào đối với trang tệp dữ liệu trong bộ nhớ đều yêu cầu một chốt độc quyền, vì vậy mỗi chuỗi cố gắng chèn vào cùng một trang phải có được chốt của trang đó. Trong khi mỗi chuỗi đang giữ chốt độc quyền, các chuỗi khác sẽ chờ PAGELATCH_EX cho trang đó, về cơ bản thực hiện chèn đồng thời vào một quy trình đồng bộ cực kỳ tắc nghẽn.
Có một số bản sửa lỗi khả thi cho sự cố này:
- Sử dụng một khóa ngẫu nhiên hơn và nhận ra rằng điều này sẽ dẫn đến phân mảnh chỉ mục, vì vậy, hãy tận dụng hệ số lấp đầy chỉ mục để giúp ngăn chặn việc tách trang
- Trải các phần chèn ra trong bảng bằng cách sử dụng một số loại cơ chế phân vùng nhân tạo
- Sử dụng kích thước hàng trong bảng dài hơn (đây rõ ràng là tùy chọn kém ngon miệng nhất)
Tôi đã thấy một điểm phát sóng chèn như thế này xuất hiện khi ai đó cố gắng loại bỏ các vấn đề phân mảnh chỉ mục bằng cách thay đổi khóa cụm GUID ngẫu nhiên thành khóa cụm danh tính int hoặc bigint, nhưng không thể kiểm tra lược đồ bảng mới trong tải sản xuất.
Tóm tắt
Cũng giống như các kiểu chờ đợi khác, hiểu chính xác điều gì PAGELATCH_XX thời gian chờ đợi là chìa khóa để hiểu cách khắc phục sự cố.
Về số liệu thống kê chờ chung có liên quan, bạn có thể tìm thêm thông tin về việc sử dụng chúng để khắc phục sự cố hiệu suất trong:
- Loạt bài đăng trên blog SQLskills của tôi, bắt đầu với số liệu thống kê Chờ hoặc vui lòng cho tôi biết nó bị ảnh hưởng ở đâu
- Thư viện Các loại Chờ và Lớp Chốt của tôi tại đây
- Khóa đào tạo trực tuyến Pluralsight của tôi SQL Server:Khắc phục sự cố về hiệu suất sử dụng thống kê chờ
- Cố vấn Hiệu suất SQL Sentry
Cho đến lần sau, chúc bạn khắc phục sự cố!