Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Tác dụng phụ không mong muốn - Phiên ngủ Giữ ổ khóa

Một cam kết tư vấn gần đây tập trung vào việc chặn các vấn đề bên trong SQL Server đang gây ra sự chậm trễ trong việc xử lý các yêu cầu của người dùng từ ứng dụng. Khi chúng tôi bắt đầu tìm hiểu các vấn đề đang gặp phải, rõ ràng là từ quan điểm của SQL Server, vấn đề xoay quanh các phiên ở trạng thái Ngủ đang bị khóa bên trong Engine. Đây không phải là một hành vi điển hình cho SQL Server, vì vậy suy nghĩ đầu tiên của tôi là có một số loại lỗi thiết kế ứng dụng đang để lại một giao dịch hoạt động trên một phiên đã được đặt lại để tổng hợp kết nối trong ứng dụng, nhưng điều này đã nhanh chóng được chứng minh là không. như trường hợp này vì các ổ khóa sau đó đã được tự động phát hành, chỉ có một sự chậm trễ trong việc này xảy ra. Vì vậy, chúng tôi phải tìm hiểu sâu hơn.

Hiểu trạng thái phiên

Tùy thuộc vào DMV bạn xem cho SQL Server, một phiên có thể có một vài trạng thái khác nhau. Trạng thái Ngủ có nghĩa là Công cụ đã hoàn thành lệnh, mọi thứ giữa máy khách và máy chủ đã hoàn thành tương tác khôn ngoan và kết nối đang chờ lệnh tiếp theo đến từ máy khách. Nếu phiên đang ngủ có một giao dịch đang mở, nó luôn liên quan đến mã chứ không phải SQL Server. Giao dịch đang được mở có thể được giải thích bởi một số điều. Khả năng đầu tiên là một quy trình với một giao dịch rõ ràng không bật cài đặt XACT_ABORT và sau đó hết thời gian chờ mà không có ứng dụng xử lý dọn dẹp chính xác như được giải thích trong bài đăng thực sự cũ này của nhóm CSS:

  • Cách hoạt động:Phiên lệnh Ngủ / Đang chờ đợi là gì

Nếu quy trình đã bật cài đặt XACT_ABORT thì nó sẽ tự động hủy giao dịch khi hết thời gian và giao dịch sẽ được khôi phục lại. SQL Server đang thực hiện chính xác những gì cần làm theo tiêu chuẩn ANSI và duy trì các thuộc tính ACID của lệnh đã được thực thi. Thời gian chờ không liên quan đến SQL Server, nó được thiết lập bởi máy khách .NET và thuộc tính CommandTimeout, do đó, liên quan đến mã chứ không phải hành vi liên quan đến SQL Engine. Đây cũng là loại vấn đề mà tôi đã nói trong loạt bài Sự kiện mở rộng của mình, trong bài đăng trên blog này:

  • Sử dụng nhiều mục tiêu để gỡ lỗi các giao dịch mồ côi

Tuy nhiên, trong trường hợp này, ứng dụng không sử dụng các quy trình được lưu trữ để truy cập vào cơ sở dữ liệu và tất cả mã được tạo bởi ORM. Tại thời điểm này, cuộc điều tra đã chuyển khỏi SQL Server và hướng đến cách ứng dụng sử dụng ORM và nơi các giao dịch sẽ được tạo bởi cơ sở mã ứng dụng.

Hiểu các giao dịch .NET

Thông thường, SQL Server kết thúc bất kỳ sửa đổi dữ liệu nào trong một giao dịch được cam kết tự động trừ khi tùy chọn đặt IMPLICIT_TRANSACTIONS được BẬT cho một phiên. Sau khi xác minh rằng điều này không được BẬT cho bất kỳ phần nào trong mã của họ, khá an toàn khi giả định rằng bất kỳ giao dịch nào còn lại sau một phiên đang Ngủ là kết quả của một giao dịch rõ ràng được mở ở đâu đó trong quá trình thực thi mã của họ. Bây giờ vấn đề chỉ là hiểu khi nào, ở đâu và quan trọng nhất là tại sao nó không bị đóng cửa ngay lập tức. Điều này dẫn đến một trong một số tình huống khác nhau mà chúng tôi sẽ phải tìm kiếm bên trong mã cấp ứng dụng của chúng:

  • Ứng dụng sử dụng TransactionScope () xung quanh một hoạt động
  • Ứng dụng sử dụng SqlTransaction () trên kết nối
  • Mã ORM bao bọc một số lệnh gọi trong nội bộ một giao dịch không được cam kết

Tài liệu cho TransactionScope khá nhanh chóng loại trừ đó là nguyên nhân có thể gây ra điều này. Nếu bạn không thể Hoàn thành phạm vi giao dịch, nó sẽ tự động quay trở lại và hủy bỏ giao dịch khi nó xử lý, vì vậy, không có nhiều khả năng điều này sẽ tiếp diễn qua các lần đặt lại kết nối. Tương tự như vậy, đối tượng SqlTransaction sẽ tự động quay trở lại nếu không được cam kết khi kết nối được đặt lại để tổng hợp kết nối, do đó, điều đó nhanh chóng trở thành yếu tố khởi đầu cho sự cố. Điều này chỉ làm mất đi quá trình tạo mã ORM, ít nhất đó là những gì tôi nghĩ, và sẽ vô cùng kỳ lạ nếu một phiên bản cũ hơn của ORM rất phổ biến thể hiện loại hành vi này theo kinh nghiệm của tôi, vì vậy chúng tôi phải tìm hiểu sâu hơn.

Tài liệu cho ORM mà họ đang sử dụng nêu rõ rằng khi bất kỳ hành động đa thực thể nào xảy ra, hành động đó sẽ được thực hiện bên trong một giao dịch. Các hành động đa thực thể có thể là lưu đệ quy hoặc lưu một tập hợp thực thể trở lại cơ sở dữ liệu từ ứng dụng và các nhà phát triển đã đồng ý rằng các loại hoạt động này xảy ra trên toàn bộ mã của họ, vì vậy đúng, ORM phải đang sử dụng các giao dịch, nhưng tại sao chúng lại như vậy đột nhiên trở thành một vấn đề.

Căn nguyên của vấn đề

Tại thời điểm này, chúng tôi đã lùi lại một bước và bắt đầu thực hiện đánh giá tổng thể toàn bộ môi trường bằng cách sử dụng New Relic và các công cụ giám sát khác có sẵn khi các vấn đề chặn xuất hiện. Nó bắt đầu trở nên rõ ràng rằng các phiên ngủ giữ khóa chỉ xảy ra khi máy chủ Ứng dụng IIS chịu tải quá mức của CPU, nhưng điều đó không đủ để giải thích cho độ trễ được thấy trong cam kết giải phóng khóa giao dịch. Nó cũng chỉ ra rằng các máy chủ ứng dụng là máy ảo chạy trên một máy chủ siêu giám sát được cho phép và thời gian chờ CPU Ready cho chúng đã tăng cao nghiêm trọng tại thời điểm xảy ra sự cố chặn dựa trên các giá trị tổng kết được cung cấp bởi VM Administrator.

Trạng thái Ngủ sẽ xảy ra với một giao dịch mở giữ khóa giữa các lệnh gọi .SaveEntity của các đối tượng đang hoàn thành và cam kết cuối cùng trong mã được tạo mã phía sau cho các đối tượng. Nếu máy chủ VM / App bị áp lực hoặc tải, thì quá trình này có thể bị trì hoãn và dẫn đến sự cố chặn, nhưng vấn đề không phải ở SQL Server, nó đang làm chính xác những gì cần làm trong phạm vi của giao dịch. Vấn đề cuối cùng là kết quả của sự chậm trễ trong việc xử lý điểm cam kết phía ứng dụng. Nhận thời gian của câu lệnh đã hoàn thành và các sự kiện đã hoàn thành RPC từ Sự kiện mở rộng cùng với thời gian sự kiện database_transaction_end cho thấy độ trễ của cả chuyến đi từ cấp ứng dụng đóng giao dịch trên kết nối mở. Trong trường hợp này, mọi thứ được nhìn thấy trong SQL Server là nạn nhân của máy chủ ứng dụng quá tải và máy chủ VM quá tải. Di chuyển / phân chia tải ứng dụng trên các máy chủ trong cấu hình cân bằng tải phần cứng hoặc NLB bằng cách sử dụng các máy chủ không được cam kết quá mức về mức sử dụng CPU sẽ nhanh chóng khôi phục cam kết ngay lập tức của các giao dịch và loại bỏ các phiên ngủ đang giữ khóa trong SQL Server.

Tuy nhiên, một ví dụ khác về một vấn đề môi trường gây ra một vấn đề trông giống như một vấn đề ngăn chặn hàng loạt. Nó luôn trả tiền để điều tra lý do tại sao chuỗi chặn không thể giải phóng các ổ khóa của nó một cách nhanh chóng.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Quản trị bảo mật dữ liệu

  2. SQL DELETE cho người mới bắt đầu

  3. Hướng dẫn dữ liệu:Sử dụng các chức năng của cửa sổ

  4. Kết nối cơ sở dữ liệu hoặc lỗi xác thực với loại có thể di chuyển

  5. Cách cài đặt Neo4j trên Ubuntu 20.04