7

Ví dụ Sql Server 2008 R2 được đề cập là máy chủ sản xuất OLTP tải nặng. Vấn đề bế tắc đã xuất hiện vài ngày trước và vẫn chưa được giải quyết. Chúng tôi đã nhận được báo cáo bế tắc Xml liệt kê các thủ tục được lưu trữ liên quan đến bế tắc và một số chi tiết khác. Tôi sẽ cố gắng liệt kê các sự kiện từ xml này trước tiên:Sự cố bế tắc trong SQL Server 2008 R2 (ứng dụng .Net 2.0)

Hai thủ tục được lưu trữ có liên quan đến bế tắc, nói SP1 và SP2. Theo báo cáo SP1 đang chạy ở cấp Cô lập "Có thể nối tiếp"SP2 đang chạy trong "ReadCommitted".

Chúng tôi đã điều tra như sau:

  • chúng tôi đang thiết lập IsolationLevel của SP1 để "Serializable" bên trong SP hoặc trong Mã? - Số

  • Có bất kỳ SP nào khác có IsolationLevel gọi là "Serializable" SP1 không? - Số

  • Bảng có được sử dụng bởi SP1 được gọi là bất kỳ SP nào khác có cách ly Cấp dưới dạng "có thể tuần tự hóa" không? - Vâng. Có SPs có Isolation Cấp thiết lập để "Serializable" và truy cập các bảng giống như SP1, nhưng chúng tôi không biết liệu họ đang chạy tại thời điểm bế tắc hay không là bế tắc
    báo cáo chỉ cho thấy SP1 và SP2.

dòng tư tưởng:
Chúng tôi đã xem xét các nguyên nhân có thể như sau:

  • Deadlock đang xảy ra vì SP1 là chạy như "Serializable". - Tại sao SP này chạy trong Serializable khi Tôi chưa đặt? Isolation leo thang cấp độ (như khóa)? Nếu chúng tôi tìm ra điều này và làm cho nó chạy như ReadCommitted, vấn đề có được giải quyết không?

  • Bất kỳ SP nào khác đang chạy, khóa bảng được sử dụng bởi SP1 và gây ra sự cố bế tắc giữa SP1 và SP2 là . - SP này không được liệt kê trong báo cáo bế tắc ? Có thể bế tắc báo cáo bỏ lỡ sự phụ thuộc như vậy không? Nếu có thì chúng tôi chỉ có thể nhận được một phần thông tin . Tuy nhiên, điều này vẫn không giải quyết cách SP1 đang chạy trong Có thể lập lại được.

Gợi ý:

  • Nếu thông tin này là không đủ trong việc giải quyết vấn đề, làm thế nào tôi có thể lấy thêm thông tin từ SQL Server cho mục đích của tôi và những gì thông tin nên tôi cố gắng thu thập?

  • Bất kỳ dòng tư tưởng nào khác mà bạn muốn theo đuổi trong việc giải quyết vấn đề này?

Cập nhật:
Đây là thông tin đăng nhập dấu vết cho bế tắc. Tôi đã thay đổi tên của SP, vv nhưng đã kiểm tra và xác minh rằng những thay đổi không bỏ lỡ bất kỳ thông tin có liên quan. Kiểm tra các ghi chú thành công mã để biết thêm về bảng, vv

?<EVENT_INSTANCE> 
    <EventType>DEADLOCK_GRAPH</EventType> 
    <PostTime>2010-09-07T11:27:47.870</PostTime> 
    <SPID>16</SPID> 
    <TextData> 
    <deadlock-list> 
     <deadlock victim="process5827708"> 
     <process-list> 
      <process id="process5827708" taskpriority="0" logused="0" waitresource="KEY: 7:72057594228441088 (8d008a861f4f)" 
        waittime="5190" ownerId="1661518243" transactionname="SELECT" lasttranstarted="2010-09-07T11:27:42.657" 
        XDES="0x80bf3b50" lockMode="RangeS-S" schedulerid="4" kpid="2228" status="suspended" spid="76" sbid="0" 
        ecid="0" priority="0" trancount="0" lastbatchstarted="2010-09-07T11:27:42.657" 
        lastbatchcompleted="2010-09-07T11:27:42.657" clientapp=".Net SqlClient Data Provider" 
        hostname="xxx" hostpid="5988" loginname="xxx" isolationlevel="serializable (4)" 
        xactid="1661518243" currentdb="7" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056"> 
      <executionStack> 
       <frame procname="SP1" line="12" stmtstart="450" stmtend="6536" 
        sqlhandle="0x0300070090cbdc7742720c00e99d00000100000000000000"> 
       Select ... from Table1, Table2, Table4, Table5 
       </frame> 
      </executionStack> 
      <inputbuf> 
       Proc [Database Id = 7 Object Id = 2010958736] 
      </inputbuf> 
      </process> 
      <process id="process5844bc8" taskpriority="0" logused="1873648" waitresource="KEY: 7:72057594228441088 (0e00ce038ed0)" 
        waittime="4514" ownerId="1661509575" transactionname="user_transaction" lasttranstarted="2010-09-07T11:27:40.423" 
        XDES="0x37979ae90" lockMode="X" schedulerid="7" kpid="3260" status="suspended" spid="104" sbid="0" ecid="0" 
        priority="0" trancount="2" lastbatchstarted="2010-09-07T11:27:43.350" lastbatchcompleted="2010-09-07T11:27:43.350" 
        clientapp=".Net SqlClient Data Provider" hostname="xxx" hostpid="5988" loginname="xxx" 
        isolationlevel="read committed (2)" xactid="1661509575" currentdb="7" lockTimeout="4294967295" 
        clientoption1="673185824" clientoption2="128056"> 
      <executionStack> 
       <frame procname="SP2" line="68" stmtstart="5272" stmtend="5598" 
        sqlhandle="0x030007003432350f109a0c00e99d00000100000000000000"> 
       UPDATE Table1 ... 
       </frame> 
      </executionStack> 
      <inputbuf> 
       Proc [Database Id = 7 Object Id = 255144500] 
      </inputbuf> 
      </process> 
     </process-list> 
     <resource-list> 
      <keylock hobtid="72057594228441088" dbid="7" objectname="Table1" indexname="Index1" 
        id="lock448e2c580" mode="X" associatedObjectId="72057594228441088"> 
      <owner-list> 
       <owner id="process5844bc8" mode="X" /> 
      </owner-list> 
      <waiter-list> 
       <waiter id="process5827708" mode="RangeS-S" requestType="wait" /> 
      </waiter-list> 
      </keylock> 
      <keylock hobtid="72057594228441088" dbid="7" objectname="Table1" indexname="Index1" 
        id="lock2ba335880" mode="RangeS-S" associatedObjectId="72057594228441088"> 
      <owner-list> 
       <owner id="process5827708" mode="RangeS-S" /> 
      </owner-list> 
      <waiter-list> 
       <waiter id="process5844bc8" mode="X" requestType="wait" /> 
      </waiter-list> 
      </keylock> 
     </resource-list> 
     </deadlock> 
    </deadlock-list> 
    </TextData> 
    <TransactionID /> 
    <LoginName>xx</LoginName> 
    <StartTime>2010-09-07T11:27:47.867</StartTime> 
    <ServerName>xxx</ServerName> 
    <LoginSid>xxx</LoginSid> 
    <EventSequence>116538375</EventSequence> 
    <IsSystem>1</IsSystem> 
    <SessionLoginName /> 
</EVENT_INSTANCE> 

SP1 được thực hiện một lựa chọn mà sẽ đưa dữ liệu từ 5 bảng khác nhau (Table1 để Table5) (sử dụng bên trong truy vấn, vv) SP2 thực hiện một bản cập nhật trên Table1 .
Một điều thú vị là một trong những cột mà SP2 cập nhật là một trường khóa ngoài trong Table1 và khóa chính của Table2 trong khi cả Table1 và Table2 là một phần của câu lệnh chọn SP1, không chắc chắn điều này có liên quan nhưng không muốn bỏ lỡ bất cứ điều gì.

LƯU Ý: indexname = "Index1" (trong biểu đồ bế tắc ở trên) - Chỉ mục1 nằm trên cùng cột là khóa ngoài trong Bảng 1 và khóa chính của Bảng 2.

+0

để bắt đầu, bạn sẽ cần phải cung cấp đầu ra từ 'DBCC TRACEON (1222, -1) 'và các bit của lược đồ liên quan đến bế tắc –

+0

Tôi đã theo dõi 1222 nhưng cách làm cho nó có sẵn. Có thể tải lên một tập tin với câu hỏi hay tôi chỉ cần dán nó với câu hỏi (thực sự lớn)? –

+0

Chỉ cần lấy một vài chuỗi bế tắc và nhúng vào câu trả lời. Sau đó cung cấp SQL cho cả hai giao dịch và lược đồ có liên quan –

Trả lời

2

Kiểm tra này MSDN article trong đó nêu:

Một mức cô lập có kết nối toàn bộ phạm vi và một khi đã đặt cho kết nối với SET TRANSACTI TRÊN tuyên bố mức độ cô lập, nó vẫn có hiệu lực cho đến khi kết nối bị đóng hoặc cách ly khác mức được thiết lập. Khi một kết nối được đóng lại và trở về hồ bơi, mức cách ly từ lệnh SET TRANSACTION ISOLATION LEVEL cuối cùng được giữ lại. Các kết nối tiếp theo sử dụng lại kết nối được gộp chung sử dụng mức cách ly có hiệu lực tại thời điểm kết nối được gộp chung.

Vấn đề là kết nối được mở bằng cấp cách ly có thể lập trình được; giao dịch liên quan đã được xử lý và do đó là kết nối nhưng kết nối không bị phá hủy và đi đến hồ bơi kết nối. Lần sau khi yêu cầu kết nối được thực hiện (với cùng một chuỗi kết nối), kết nối này đã được trả về và vì truy vấn không chỉ định bất kỳ mức cô lập nào, nó đang thực hiện ở mức cô lập Serializable. Về cơ bản, nếu bạn có một hồ bơi kết nối và mở một kết nối ở một mức cách ly cụ thể, hãy nói Serializable, sau đó kết nối sẽ trở lại hồ bơi với mức cách ly được đặt thành Serializable. Lần sau khi bạn yêu cầu kết nối, bạn không thể chắc chắn rằng kết nối này sẽ không được trả lại vì vậy ngay cả thông qua mức cô lập mặc định là ReadCommitted, bạn có thể nhận được một trong các kết nối "Serializable" này. Một cảnh báo khác là mỗi khi bạn thiết lập mức cô lập thành Serializable (hoặc bất kỳ thứ gì khác cho vấn đề đó), bạn có thể chọn các kết nối khác nhau và từ từ bạn có thể gây ô nhiễm ngày càng nhiều kết nối trong nhóm kết nối. Serializable (hoặc bất cứ điều gì bạn đặt).

Tôi không tìm thấy bất kỳ cơ chế nào để đặt lại kết nối đang xử lý (khi nó quay trở lại nhóm kết nối sau khi thực hiện truy vấn của tôi). Một cách giải quyết khác là đặt lại mức cô lập một cách rõ ràng cho mỗi kết nối. Nhưng điều này là tẻ nhạt.

Vì vậy, giải pháp thay thế tốt nhất là tạo các hồ bơi kết nối riêng biệt cho các mức cách ly khác nhau.

1

thêm bằng (nolock) sau các bảng được chọn trong sp1 để đảm bảo không thể thêm khóa đọc vào các bảng cụ thể đó.

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