日期:2014-05-17  浏览次数:20566 次

数据库事务到底怎么执行的?
比如事务开始后,我执行了3条增删改命令,然后Commit提交,只要有一条不成功就都不成功。

比如它在Commit之前,执行3条增删改命令,是否真的修改了数据库中的数据?假如第一条插入一条记录到A表,执行第二句时出错,回滚,是不是它自动对A表执行一条删除命令?

网上也看了些资料,都是泛泛而谈,一直没理解。菜鸟,见笑了~~

------解决方案--------------------
执行,但如遇错误回滚。
------解决方案--------------------
回滚,就是将数据库回到原先状态,不是简单删除插入行。
------解决方案--------------------
假如第一条插入一条记录到A表,执行第二句时出错,回滚,是不是它自动对A表执行一条删除命令?
--> Yes,It called 'transaction rollback'.
------解决方案--------------------
探讨
假如第一条插入一条记录到A表,执行第二句时出错,回滚,是不是它自动对A表执行一条删除命令?
--> Yes,It called 'transaction rollback'.

------解决方案--------------------
这个第一要看你的以下设定。具体可以看联机帮助中的示例如下:
SET XACT_ABORT
指定当 Transact-SQL 语句产生运行时错误时,Microsoft® SQL Server? 是否自动回滚当前事务。

语法
SET XACT_ABORT { ON | OFF }

注释
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。

对于大多数 OLE DB 提供程序(包括 SQL Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是提供程序支持嵌套事务时。有关更多信息,请参见分布式查询和分布式事务。 

SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。

示例
下例导致在含有其它 Transact-SQL 语句的事务中发生违反外键错误。在第一个语句集中产生错误,但其它语句均成功执行且事务成功提交。在第二个语句集中,SET XACT_ABORT 设置为 ON。这导致语句错误使批处理终止,并使事务回滚。 

CREATE TABLE t1 (a int PRIMARY KEY)
CREATE TABLE t2 (a int REFERENCES t1(a))
GO
INSERT INTO t1 VALUES (1)
INSERT INTO t1 VALUES (3)
INSERT INTO t1 VALUES (4)
INSERT INTO t1 VALUES (6)
GO
SET XACT_ABORT OFF
GO
BEGIN TRAN
INSERT INTO t2 VALUES (1)
INSERT INTO t2 VALUES (2) /* Foreign key error */
INSERT INTO t2 VALUES (3)
COMMIT TRAN
GO

SET XACT_ABORT ON
GO

BEGIN TRAN
INSERT INTO t2 VALUES (4)
INSERT INTO t2 VALUES (5) /* Foreign key error */
INSERT INTO t2 VALUES (6)
COMMIT TRAN
GO

/* Select shows only keys 1 and 3 added. 
Key 2 insert failed and was rolled back, but
XACT_ABORT was OFF and rest of transaction
succeeded.
Key 5 insert error with XACT_ABORT ON caused
all of the second transaction to roll back. */

SELECT * 
FROM t2
GO

DROP TABLE t2
DROP TABLE t1
GO

-----------
其他的情况。如楼上各位所言。
------解决方案--------------------
探讨
引用:
回滚,就是将数据库回到原先状态,不是简单删除插入行。


那么在Commit之前插入记录操作怎么解释呢,它没有真的插入吗?你说的“将数据库回到原先状态”,究竟采用什么方法使其“回到原先状态”的?

------解决方案--------------------
正常的事务会都写入事务日志中(任何恢复模式都会写日志),并且记录状态,当在【同一个事务】中的操作完成了,如果显式开启事务,那么要显式提交(commit)或者回滚(rollback)。在事务日志中,无论提交还是回滚都会记录,当发生Checkpoint(默认一分钟一次)或者lazy Writer(不定期)或者日志备份时,会把【已提交】的事务写入数据文件,如果在没写入之前就要还原,那么还原的最后步骤也会写入到数据文件,然后把未提交的事务撤销。
建议任何时候使用显式开启事务,这样可读性更高,遗漏也更少。在being tran抱着的代码,都视为一个事务,要么全做,要么全部做。
------解决方案--------------------
回滚的实际操作无非时将insert 的数据转为delete,delete的数据进行insert处理,
------解决方案--------------------
直接回滚到未插入的状态,并不是单纯的删除数据。
------解决方案--------------------
探讨

感谢楼上各位的回答,不过还有个疑惑:SQLserver可以用日志来记录状态和维护事务,那么想Access、SQLite貌似没有日志文件啊,它们又是怎么维护事务的呢?