2009-01-27 24 views
5

我在事務範圍內從.NET調用的SQL Server T-SQL中存儲了過程。如何在T-SQL中的事務外執行插入和更新

在我的存儲過程中,我正在做一些日誌記錄到一些審計表。我在審計表中插入一行,然後在事務中稍後通過更新填充更多信息。

我發現的是,如果有幾個人同時嘗試同樣的事情,其中​​1或2個人將成爲交易死鎖受害者。目前,我正在假設在插入審計表時發生某種鎖定。

我想執行對正在執行的事務之外的審計表的插入和更新,因此無論如何審計都會發生,即使事務回滾。我希望這可以阻止發生的任何鎖定,允許一個以上的人一次執行該程序。

任何人都可以幫助我在T-SQL中做到這一點?

感謝, 豐富

更新 - 因爲我已經發現,審計是無關的事務死鎖,由於使用SQL事件探查喬希的建議追查僵局的根源。

+0

你審計表有外鍵到你的主'熱'表嗎? – 2009-01-27 14:05:51

+0

種類 - 如果我插入一個新行,我創建一個'插入'審計記錄。然後我創建新行,包括審計表中的密鑰以顯示創建該行的審計操作。然後,我使用新行的ID更新審計記錄,以顯示創建的內容。雖然沒有關係。 – Rich 2009-01-27 14:39:42

+0

好吧,我只是GOOGLE:抑制sql事務,這個問題是第三個有趣的連接 – JoshBerke 2009-01-27 14:56:12

回答

1

你爲什麼要更新審計表?如果你只是在做插入,你可能有助於防止鎖升級。你是否也檢查了死鎖痕跡來確定你到底是死鎖?

您可以通過啓用trace flag 1204來做到這一點。或者運行SQL Profiler。這會給你詳細的信息,讓你知道什麼樣的死鎖(鎖,線程,平行等...)。

查看關於Detecting and Ending Deadlocks的文章。

另一種執行審計的方法是通過將所有日誌記錄事件發送到應用程序層的隊列中完全與業務事務分離,從而最大限度地減少日誌對業務事務的影響,但對於現有應用。

1

您可以將審計保存到表變量(不受事務影響),然後在SP末端(在事務範圍外)將行插入審計表。

但是,這聽起來像你正在試圖解決症狀,而不是問題。你可能想追蹤死鎖並修復它們。

5

TranactionScope支持禁止:

using (TransactionScope scope = new TransactionScope()) 
{ 

    // Transactional code... 


    // Call a SQL stored procedure (but suppress the transaction) 
    using (TransactionScope suppress = new TransactionScope(TransactionScopeOption.Suppress)) 
    { 
     using (SqlConnection conn = new SqlConnection(...)) 
     { 
      conn.Open(); 
      SqlCommand sqlCommand = conn.CreateCommand(); 
      sqlCommand.CommandType = CommandType.StoredProcedure; 
      sqlCommand.CommandText = "MyStoredProcedure"; 
      int rows = (int)sqlCommand.ExecuteScalar(); 
     } 
    } 

    scope.Complete(); 

} 

但我不得不問爲什麼日誌/審計將在交易之外運行?如果事務回滾,您仍然會提交審計/日誌記錄,這可能不是您想要的。

您尚未提供有關如何記錄日誌的許多信息。您的審計表是否有外鍵指向您的主要活動表?如果是這樣,請刪除外鍵(假設審計記錄僅來自「已知」應用程序)。