如果不将事务提交到数据库(例如SQL Server),会发生什么情况?


108

假设我有一个查询:

begin tran
-- some other sql code

然后我忘记提交或回滚。

如果另一个客户端尝试执行查询,将会发生什么?

Answers:


148

只要您不提交回滚事务,它仍在“运行”并可能持有锁。

如果您的客户端(应用程序或用户)在提交之前关闭了与数据库的连接,则所有仍在运行的事务将被回滚并终止。


1
嗯,好吧,我知道这是在创建某种锁。我不确定关闭连接是否真的会使我脱离此状态。问题是尝试提交时出现错误。现在我关闭了连接,一切正常。
Charbel

12
旁注:如果使用Management Studio,关闭查询窗口将关闭连接
Joe Phillips

3
@BradleyDotNET:是的,绝对
marc_s

2
请记住,默认情况下,如果关闭查询窗口/连接,SQL Server Management Studio会自动提交。
努诺2015年

1
请注意,当客户端在事务处于活动状态时关闭连接时,它并不总是回滚-这取决于客户端和数据库。例如,当Java应用程序关闭与Oracle数据库的连接时,所有打开的连接都会自动提交。
AviD

38

您实际上可以自己尝试一下,这应该有助于您了解它的工作原理。

在Management Studio中打开两个窗口(选项卡),每个窗口都有自己的sql连接。

现在,您可以在一个窗口中开始事务,执行诸如插入/更新/删除之类的操作,但尚未提交。然后在另一个窗口中,您可以从事务外部查看数据库的外观。根据隔离级别,表可能会被锁定,直到提交第一个窗口为止,或者您可能(尚未)看到到目前为止其他事务已完成的工作,等等。

尝试使用不同的隔离级别,并且没有锁定提示,以查看它们如何影响结果。

另请参阅在事务中引发错误时会发生什么。

了解所有这些东西的工作方式非常重要,否则很多时候您会被sql所困扰。

玩得开心!GJ。


好的,但是至少在发出提交之前,是否至少将事务写入日志?例如,假设我要启动事务,请在执行提交之前运行插入命令并“执行其他操作”。我的插入命令会被写入日志吗?这样,如果服务器在执行commit ..之前崩溃了,它可以返回到原来的位置,而我可以稍后再提交commit(只要我做完“其他事情”)。
user1870400 '19

16

事务旨在完全运行或根本不运行。完成事务的唯一方法是提交,任何其他方法都将导致回滚。

因此,如果您先开始然后不提交,则它将在连接关闭时回滚(因为事务被中断而未标记为完成)。


那是应该的,但并非总是如此。
FalcoGer

...例如,不支持事务的mySQL的MyISAM 。
Piskvor于

3

取决于传入事务的隔离级别。

SQL事务隔离说明


6
事务的行为不取决于隔离级别。他们可能引起的锁数量确实如此。
marc_s

我非常确定连接可以读取哪些数据,这绝对取决于隔离级别。如果将隔离设置为READ UNCOMMITTED,则可以读取尚未提交的数据,并且实际上可以在轨道的某个点回滚,但这可以确保没有锁定。如果您已将READ COMMITTED(读取已提交)作为隔离级别,则您将无法读取未提交的行-除非您使用SNAPSHOT,否则第二个客户端将挂起。
Xhalent 2011年

2

当您打开交易时,没有任何东西会被自己锁定。但是,如果您在该事务内执行某些查询,则根据隔离级别,某些行,表或页面将被锁定,因此它将影响尝试从其他事务访问它们的其他查询。


1

交易示例

开始转换tt

您的sql语句

如果发生错误,则回滚tran tt否则提交tran tt

只要您尚未执行commit tran tt,数据就不会更改


1
请注意,命名事务不仅在MS SQL中是不必要的,还会给人一种错误的控制感。 BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Y例如,它不起作用。见stackoverflow.com/questions/1273376/...

0

除了可能引起的潜在锁定问题之外,您还会发现事务日志开始增长,因为它们不能被截断超过活动事务的最小LSN,并且如果使用快照隔离,则tempdb中的版本存储将增长类似的原因。

您可以dbcc opentran用来查看最早的未结交易的详细信息。


0

任何未提交的事务将使服务器处于锁定状态,并且其他查询将不会在服务器上执行。您需要回滚事务或提交它。关闭SSMS也将终止事务,这将允许执行其他查询。


-4

该行为未定义,因此您必须显式设置提交或回滚:

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

“如果禁用了自动提交模式,并且在没有显式提交或回滚上一次更改的情况下关闭了连接,则将执行隐式COMMIT操作。”

Hsqldb进行回滚

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

结果是

2011-11-14 14:20:22,519主要信息[SqlAutoCommitExample:55] [启用了AutoCommit = false] 2011-11-14 14:20:22,546主要信息[SqlAutoCommitExample:65] [在数据库中找到0#用户]


2
这对于Oracle可能是正确的(我不知道),但发问者正在询问有关MS-SQL的问题
PaulG 2012年

第一个引号适用于JDBC驱动程序,不适用于服务器。
djechlin 2013年
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.