2009-01-27 27 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(); 

} 

但我不得不问为什么日志/审计将在交易之外运行?如果事务回滚,您仍然会提交审计/日志记录,这可能不是您想要的。

您尚未提供有关如何记录日志的许多信息。您的审计表是否有外键指向您的主要活动表?如果是这样,请删除外键(假设审计记录仅来自“已知”应用程序)。