【问题标题】:SQL Update via triggers without database locking通过触发器进行 SQL 更新,无需数据库锁定
【发布时间】:2011-02-03 23:48:18
【问题描述】:

有没有办法更新审计表中的记录(通过触发器),而不会因为触发触发器的更新在事务内部而锁定该记录。

所以我们有一个用户表和一个触发器,它在插入、更新、删除时触发并将更改的值记录到某个审核表中,但是我不希望审核表被锁定以防止其他触发器触发执行操作审计表。

编辑: 澄清一下,我遇到的问题是多个表通过不同的触发器向同一个审计表报告,因此对一个表的更新会锁定所有其他表的更新。至于事务是否回滚的问题,这不是一个问题,因为审计表只是用于更改跟踪,如果记录回滚,如果审计表不回滚也不是问题。

我想到了一种可行的方法,但我不知道这是否可行(或如何实现),有没有办法让触发器使用新连接而不是最初调用的连接?

【问题讨论】:

  • 如果事务回滚,您真的希望另一个进程读取审计表中的记录吗?
  • 我认为,是的,您确实希望锁定审计表的数据。您真正的问题可能是您在审计表上有一个顺序(可能是聚集的)主键索引,它会热点审计表的叶节点,导致所有插入审计表到同一个叶节点页面中时间。将主键更改为具有更多随机排序的东西,这应该可以解决您的锁定问题。

标签: sql transactions deadlock


【解决方案1】:

不可能创建一个至少不对正在写入的记录/页面设置写锁的操作。否则 SQL Server 会一直存在一致性问题。你应该从相反的角度看——其他需要访问审计表的进程(审计通常意味着只读,几乎没有更新)应该使用

SET TRANSACTION ISOLATION LEVEL SNAPSHOT
or
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

将从审计表中脏读(或版本化而不加锁)

如果你必须..
有一种偷偷摸摸的方法可以使用 Service Broker 将写入与事务隔离,而是将数据插入中间表并让 SSSB 异步激活线程为您写入审计记录,从而使您的原始长时间运行的事务保持未提交状态。

【讨论】:

  • 从数据保存的角度来看,SQL 似乎能够正常工作,直到记录锁升级为页面锁,我们已经降低了发生这种情况的可能性,因此这个问题回答了有关读取审计表的任何问题系统运行时
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-04
  • 2012-02-23
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
  • 1970-01-01
相关资源
最近更新 更多