我可以用SQL Server打开可停止的事务吗?

时间:2011-08-02 18:17:27

标签: sql sql-server transactions

我正在寻找类似于SQL事务的东西。我需要交易提供的常规保护,但我不希望它减慢任何其他人的速度。

想象一下,客户端A连接到数据库并运行以下命令:

BEGIN TRAN
SELECT (something)
(Wait a few seconds maybe.)
UPDATE (something)
COMMIT

在SELECT和UPDATE之间,客户端B出现并尝试进行查询,在正常情况下,最终必须等待A进行COMMIT。

我想要的是客户端A以这样的方式打开它的事务,B应该出现并执行它的查询,客户端A会发现它的事务立即回滚并且后续命令失败。客户B只会遇到最小的延迟。

(请注意,SELECT和UPDATE只是说明性命令。)

...更新

我有一个高优先级的任务(客户端B),有时(一个月一次)得到一个SQL超时错误,一个低优先级任务(客户端A)的事务导致超时。我宁愿低优先级任务失败并在下一个周期重新尝试。

我最终通过完全消除事务并用一组非正式标志替换它们来解决这个问题。如果引发了正确的标志集,那么查询被重构为仅执行某些操作,并且我添加了一些清除废弃记录的内容,以便回滚在过去清除过。

我通过消除交易修复了我的交易问题。

4 个答案:

答案 0 :(得分:6)

使用SNAPSHOT隔离级别会阻止B阻止。 B会在A发出BEGIN TRANSACTION之前的状态中看到数据B。除非{{1}}修改数据,否则它们永远不会相互阻挡。

答案 1 :(得分:2)

那是回到前面。

你不能让以后的客户中止早先的交易:那很混乱。

您可以拥有snapshot isolation,以便客户端B具有一致的视图,并且(主要)不被客户端A阻止。另外Wikipedia用于更一般的内容

或许更全面地描述您的问题,以便我们为此提供建议......

答案 2 :(得分:2)

虽然根本不是一个事务,但Optimistic Concurrency可能很有用 - 默认情况下它在LINQ2SQL等中使用。

一般的想法是读取数据 - 可以独立进行修改 - 然后用“检查”写回数据(这与比较和交换大致相当)。如果检查失败,应用程序将决定做什么(重新启动进程,继续进行,失败)。

这自然不适用于所有场景,并且可能无法检测到许多交互,例如在“读取”和“写入”之间添加的新项目。实际的读写都可以在具有适当隔离级别的单独事务中进行;单独的交易可能允许交叉的其他交易。

当然,根据确切的问题和相互作用......不同的隔离级别和/或更精细的锁定可能就足够了。

快乐的编码。

答案 3 :(得分:1)

我见过的一件事(但我担心我没有任何代码可以使用它)是有事务A产生另一个进程然后监视事务。如果它看到事务导致的任何阻塞,那么它会立即向spid发出KILL

如果我能找到这个代码,那么我会在这里添加。