Jan*_*eYu 11 transaction sql-server-2012
我只是想知道如果您在数据库中开始事务并忘记提交或回滚它会发生什么。服务器会宕机吗?假设您将其放置了 3 天。
也有使用它的用户假设其他用户不知道有一个未关闭的事务(假设用户只是在数据库中插入数据)。这一行动的后果是什么?
Mic*_*een 15
拥有一个开放的交易本身几乎没有任何后果。一个简单的
BEGIN TRANSACTION
-- wait for a while, doing nothing
-- wait a bit longer
COMMIT
Run Code Online (Sandbox Code Playgroud)
在最坏的情况下,将保存几个字节的状态值。没什么大不了。
大多数程序会在事务中做实际工作,这是另一回事。事务的意义在于您可以确保数据库中的多个事实同时为真,尽管有其他用户同时写入同一个数据库。
以在银行账户之间转账的典型例子为例。系统必须确保源帐户存在,有足够的资金,目标帐户存在,并且借方和贷方都发生或都不发生。当其他交易发生时,它必须保证这一点,甚至可能是在这两个帐户之间。系统通过锁定相关表来确保这一点。使用了哪些锁,以及您看到了多少其他人的工作,都由事务隔离级别控制。
因此,如果您做了大量工作,很有可能其他事务将排队等待您持有锁的对象。这将降低系统的整体吞吐量。最终它们会达到超时限制并失败,这对整个系统行为来说是一个问题。如果您使用乐观隔离级别,当您尝试提交时,您的事务可能会因为其他人的工作而失败。
持有锁会占用系统资源。这是系统无法用于处理其他请求的内存,从而降低了吞吐量。
如果执行了大量工作,系统可能会选择执行锁升级。整个表将被锁定,而不是锁定单个行。那么更多的并发用户会受到影响,系统吞吐量会进一步下降,对应用程序的影响会更大。
数据更改被写入日志文件,保护它们的锁也是如此。在事务提交之前,这些不能从日志中清除。因此,非常长的事务可能会导致日志文件膨胀及其相关问题。
如果当前工作使用 tempdb,这很可能适用于大型工作负载,则那里的资源可能会一直占用到事务结束。在极端情况下,这可能会导致其他任务失败,因为它们不再有足够的空间。我曾遇到过编码错误的 UPDATE 填充了 tempdb,因此没有足够的磁盘用于报告的 SORT 并且报告失败。
如果您选择回滚事务,或者系统出现故障并恢复,则系统再次可用所需的时间将取决于执行的工作量。简单地打开一个事务不会影响恢复时间,它是执行了多少工作。如果事务打开但空闲一个小时,恢复将几乎是瞬时的。如果那个小时一直在写,经验法则是恢复时间也将是大约一个小时。
如您所见,长事务可能会出现问题。对于 OLTP 系统,最佳实践是每个业务事务有一个数据库事务。用于以块为单位的批处理工作流程输入,频繁提交,并编码重新启动逻辑。通常可以在单个数据库事务中处理数千条记录,但这应该针对并发和资源消耗进行测试。
不要试图走向另一个极端,完全避免事务和锁定。如果您需要保持数据的一致性(以及您为什么要使用数据库?)隔离级别和事务具有非常重要的用途。了解您的选择,并决定您准备在应用程序的每个部分采用什么样的并发性和正确性平衡。
小智 6
您最大的后果将是阻塞事务中使用的对象。特别是如果您假设您的用户正在插入数据,那么长时间运行的事务可能包括常用表上的 SELECT 语句。您用户的更新语句可能无法获得完成更新或插入所需的必要锁定。
可能发生的次要事件是日志文件活动,例如,如果您正在更新大型数据集,则该事务使用的日志部分在该事务期间保持活动状态。在提交或回滚事务之前,您将无法重用日志的该部分。在您可能处于高度活跃的 OLTP 系统中的情况下,这可能会导致您的日志文件快速增长,填满您的存储设备。