长时间在MSSQL中打开事务会产生什么影响?


11

我只是想知道如果您在数据库中开始事务并忘记提交或回滚该怎么办。服务器会停机吗?可以说您离开了3天。

还有一些正在使用它的用户,假设其他用户不知道有未完成的事务(假设用户只是在数据库中插入数据)。此操作的后果是什么?

Answers:


14

本身进行公开交易几乎不会有任何后果。一个简单的

BEGIN TRANSACTION
-- wait for a while, doing nothing
-- wait a bit longer
COMMIT

在最坏的情况下,将保留几个字节的状态值。没什么大不了的。

大多数程序将在事务内完成实际工作,这是另一回事。事务的重点是,即使有其他用户同时写入同一数据库,您也可以确保数据库中的多个事实同时成立。

以在银行帐户之间转移资金的典型例子为例。系统必须确保源帐户存在,有足够的资金,目标帐户存在,并且借方和贷方都发生或不发生。它必须在其他交易发生时甚至在这两个帐户之间进行交易时保证这一点。系统通过在相关表上锁定来确保这一点。采取什么锁以及您看到多少其他人的工作由事务隔离级别控制

因此,如果您做了很多工作,很有可能其他事务将排队等待您持有锁的对象。这将降低系统的整体吞吐量。最终,它们将达到超时限制并失败,这是整个系统行为的问题。如果使用乐观隔离级别,则由于其他人的工作,当您尝试提交时,事务可能会失败。

持有锁会占用系统资源。这是系统无法用于处理其他请求的内存,从而降低了吞吐量。

如果执行了大量工作,则系统可以选择执行锁定升级。而不是锁定单个行,整个表将被锁定。然后,更多的并发用户将受到影响,系统吞吐量将进一步下降,并且对应用程序的影响将更大。

数据更改以及保护它们的锁都会写入日志文件。在事务提交之前,无法从日志中清除这些内容。因此,很长的事务可能会导致日志文件膨胀以及相关的问题。

如果当前工作使用的是tempdb(可能适用于大型工作负载),则那里的资源可能会被占用,直到事务结束。在极端情况下,这可能会导致其他任务失败,因为不再有足够的空间容纳它们。我曾经遇到过这样的情况,即编码不足的UPDATE填充了tempdb,因此没有足够的磁盘用于报告的SORT,并且报告失败。

如果选择回滚事务,或者系统发生故障并恢复,则系统再次可用所需的时间将取决于执行了多少工作。简单地打开一个事务不会影响恢复时间,这是执行了多少工作。如果事务已打开但闲置了一个小时,则恢复几乎是瞬时的。如果在该小时内不断写作,则经验法则是恢复时间也将是一个小时左右。

如您所见,长时间的交易可能会出现问题。对于OLTP系统,最佳实践是每个业务事务只有一个数据库事务。对于批处理工作,以频繁提交的块形式输入过程,并重新编码逻辑。通常,在一个数据库事务中可以处理几千条记录,但是应该测试并发性并减少消耗。

不要试图走到另一个极端,避免交易和完全锁定。如果您需要保持数据内的一致性(以及为什么还要使用数据库?),隔离级别和事务将起到非常重要的作用。了解有关您的选项的信息,并确定在应用程序的每个部分中准备使用的并发性和正确性之间的平衡。


即使开放三天?
JanLeeYu16年

是的,甚至三天。重要的是TX打开时已完成的工作量,而不仅仅是打开了多长时间。当然,作为一名DBA,您可能想问问交易的所有者为什么他们需要这么长时间才能开放交易。当我管理一个DBA团队时,我记录了所有已打开超过30分钟的TX,并与所有者进行了交谈。
Michael Green

好。感谢您的出色解释。虽然每个人都做得很好。
JanLeeYu16年

真是令人欣慰...再次感谢您的回答。
JanLeeYu16年

是的,“ UPDATE编码错误”。看到了。循环内的一条update语句没有限定某些名称,并导致1 = 1的行为,因此它为循环的每次迭代更新了整个表(这也将错误的数据也放在了大多数行中)。
jpmc26 2016年

6

您最大的后果将是阻塞事务中使用的对象。特别是如果您假设用户正在插入数据,则该长时间运行的事务可能会在常用表上包含SELECT语句。用户的更新语句可能无法获得完成其更新或插入所需的必要锁定。

可能发生的第二件事是日志文件活动,例如,如果您要更新大型数据集,则在该事务期间,事务正在使用的日志部分将保持活动状态。在事务被提交或回滚之前,您将无法重用该部分日志。在您可能处于活动频繁的OLTP系统中的情况下,这可能会导致日志文件快速增长,从而填满存储设备。


例如,创建交易的人已与服务器断开连接,他/她是否能够再次登录到服务器以关闭交易?
JanLeeYu16年

这取决于交易是否在使用MSDTC的环境中,它可能是孤立交易。在那种情况下,没有用户将不再能够自己关闭它……DBA将不得不介入来处理它。除此之外,您通常应该看到SQL Server在断开连接时取消了该事务……但是对于大型事务,这再次可能并非每次都如此。

万一发生这种情况,管理员是否仍然可以关闭交易权限?
JanLeeYu16年

我无法回答这一点,这完全取决于。我曾经遇到过必须重新启动服务器,或者实例故障转移到辅助节点/副本的情况。

4

不完整的事务可能持有大量锁并导致阻塞

如果由于查询超时或由于在事务中间取消了批处理而未发出COMMIT或ROLLBACK语句来完成事务而未完成事务,则该事务将保持打开状态,并且在该事务期间获取的所有锁将继续将要举行。在同一连接下执行的后续事务将被视为嵌套事务,因此不会释放在这些完成的事务中获取的所有锁。从同一连接执行的所有事务都会重复出现此问题,直到执行ROLLBACK。结果,持有大量锁,用户被阻止,交易丢失,从而导致数据与您期望的数据不同。

资源


例如,创建交易的人已与服务器断开连接,他/她是否能够再次登录到服务器以关闭交易?
JanLeeYu16年

一旦SQL Server知道连接已丢失,它将回滚事务。参见dba.stackexchange.com/questions/47404/…。如果同一用户重新连接,它将是一个不同的会话,因此无法以某种方式“采用”旧事务。
Michael Green
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.