我在SQL Server T-SQL中存储了在事务范围内从.NET调用的过程。
在我的存储过程中,我正在做一些记录到一些审计表。我在审核表中插入一行,然后在事务中稍后通过更新填充更多信息。
我发现,如果少数人同时尝试同样的事情,其中1或2人将成为交易死锁的受害者。目前我假设在插入审计表时发生了某种锁定。
我想在我正在执行的事务之外执行审计表的插入和更新,这样即使事务回滚,审计仍会发生。我希望这可能会阻止任何锁定发生,允许一个人同时执行该程序。
任何人都可以帮我在T-SQL中执行此操作吗?
谢谢, 富
更新 - 我发现审计与事务死锁无关,这要归功于Josh建议使用SQL事件探查器来追踪死锁的来源。
答案 0 :(得分:5)
TranactionScope支持Suppress:
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();
}
但我不得不质疑为什么日志/审计会在事务之外运行?如果事务被回滚,您仍然会提交审计/记录记录,这可能不是您想要的。
您没有提供有关如何记录的大量信息。您的审计表是否具有指向主活动表的外键?如果是这样,请删除外键(假设审计记录仅来自'已知'应用程序)。
答案 1 :(得分:2)
您可以将审核保存到表变量(不受事务影响),然后在SP的末尾(在事务范围之外)将行插入审计表。
然而,听起来你正试图解决症状而不是问题。您可能想要追踪死锁并修复它们。
答案 2 :(得分:1)
为什么要更新审核表?如果您只是进行插入,则可能有助于防止锁定升级。您是否还检查了死锁跟踪以确定您究竟是什么死锁?
您可以通过启用trace flag 1204来执行此操作。或运行SQL事件探查器。这将为您提供详细信息,让您知道什么样的死锁(锁,线程,并行等...)。
查看Detecting and Ending Deadlocks上的这篇文章。
执行审核的另一种方法是通过将所有日志记录事件发送到应用程序层的队列来完全地从业务事务中解耦,这样可以最大限度地减少日志记录对业务事务的影响,但对于现有应用程序来说,这可能非常大
答案 3 :(得分:0)
我有一个类似的要求,我需要将错误记录到错误日志表中,但发现Rollback正在擦除它们。
通过将先前插入的错误记录弹出到表变量中,调用Rollback,然后将记录推回(插入)到表中来解决此问题。
像魅力一样工作,但代码很乱,因为它必须是内联的。无法将ROLLBACK放入存储过程,否则将出现“EXECUTE后的事务计数...”错误。