事务的概念

一 什么是事务

事务是由相关操作构成的一个完整的操作单元。两次连续成功的COMMIT或ROLLBACK之间的操作,称为一个事务。在一个事务内,数据的修改一起提交或撤销,如果发生故障或系统错误,整个事务也会自动撤销。

比如,我们去银行转账,操作可以分为下面两个环节:

(1) 从第一个账户划出款项。

(2) 将款项存入第二个账户。

在这个过程中,两个环节是关联的。第一个账户划出款项必须保证正确的存入第二个账户,如果第二个环节没有完成,整个的过程都应该取消,否则就会发生丢失款项的问题。整个交易过程,可以看作是一个事物,成功则全部成功,失败则需要全部撤消,这样可以避免当操作的中间环节出现问题时,产生数据不一致的问题。

一个事务是由一个可执行的SQL语句开始,一个可执行SQL语句产生对实例的调用。在事务开始时,被赋给一个可用回滚段,记录该事务的回滚项。一个事务以下列任何一个出现而结束。数据库事务是一个逻辑上的划分,有的时候并不是很明显,它可以是一个操作步骤,也可以是多个操作步骤。

我们可以这样理解数据库事物:对数据库所做的一系列修改,在修改过程中,暂时不写入数据库,而是缓存起来,用户在自己的终端可以预览变化,直到全部修改完成,并经过检查确认无误后,一次性提交并写入数据库,在提交之前,必要的话所做的修改都可以取消。提交之后,就不能撤销,提交成功后其他用户才可以通过查询浏览数据的变化。

以事务的方式对数据库进行访问,有如下的优点:

* 把逻辑相关的操作分成了一个组。

* 在数据永久改变前,可以预览数据变化。

* 能够保证数据的读一致性。


数据库中事务处理
Transaction是SQL Server中的一个逻辑工作单元,该单元将被作为一个整体进行处理。事务保证连续多个操作必须全部执行成功,否则必须立即返回回复到未执行任何操作的状态,即执行事务的结果要不全部将数据所要执行的操作完成,要不全部数据都不修改。
1.事务的概述

1.1事务的由来
在SQL Server中使用DELETE或UPDATE语句对数据库进行更新时,一次只能操作一个表,这会带来数据库的数据不一致的问题。

1.2事务属性
由于事务是一个逻辑单元,当事务执行遇到错误时,将取消事务所作的修改。一个逻辑单元必须具有4个属性:原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability),这些属性称为ACID。
Atomicity:要么全部执行,要么全不执行
Consistency:事务完成以后,必须使数据库都保持一致的状态。事务必须遵守数据库的约束和规则,结束时,所部数据结构(如B树索引或双向链表)都必须是正确的。
Isolation:一个事务所作的修改必须与任何其他并发事务所作的修改隔离。事务查看数据时数据所处的态, 要么是另一并发事务修改它之前的状态,要么是另一事务修改之后的状态。事务不会查看中间状态的数据,这称为可串行性。
Durability:事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。

1.3事务模式
应用程序主要通过指定事务启动和结束的时间来控制事务。系统还必须能够正确处理那些在事务完成之前便终止事务的错误。
事务是在连接层记进行管理的,当事务在一个连接上启动时,在该连接上执行的所有语句在该事务结束之前都是该事务的一部分。
SQL Server中以三种模式管理事务:
自动提交模式:系统默认模式,每条单独的语句都是一个事务,在此模式下,每条T-SQL语句在成功执行后都被自动提交。如果遇到错误,则自动回滚该语句。
显示事务模式:该模式允许用户定义事务的启动和结束,事务以BEGINTRANSATION语句显示开始,以COMMIT或ROLLBACK语句显示结束。
隐式事务模式:在当前事务完成提交或回滚后,新事务自动启动。隐式事务不需要显示开始,但需要语句来提交或回滚语句。生成隐性事务链。

2.事务管理

2.1启动和结束事务

2.1.1 显示启动事务
语法格式
BEGIN TRAN [ SACTION ] [ transaction_name | @tran_name_variable
[ WITH MARK [ 'description' ] ] ]

参数
transaction_name
是给事务分配的名称。transaction_name 必须遵循标识符规则,但是不允许标识符多于 32 个字符。仅在嵌套的 BEGIN...COMMIT 或 BEGIN...ROLLBACK 语句的最外语句对上使用事务名。
@tran_name_variable
是用户定义的、含有有效事务名称的变量的名称。必须用 char、varchar、nchar 或 nvarchar 数据类型声明该变量。
WITH MARK ['description']
指定在日志中标记事务。Description 是描述该标记的字符串。
如果使用了 WITH MARK,则必须指定事务名。WITH MARK 允许将事务日志还原到命名标记。

2.1.2隐式启动事务
通过 API 函数或 Transact-SQL SET IMPLICIT_TRANSACTIONS ON 语句,将隐性事务模式设置为打开。下一个语句自动启动一个新事务。当该事务完成时,再下一个 Transact-SQL 语句又将启动一个新事务。应用程序再使用SET IMPLICIT_TRANSACTIONS OFF语句关闭隐式事务模式。
eg:
CREATE TABLE imp_tran
(num char(2) NOT NULL,
cname char(6) NOT NULL)
GO
SET IMPLICIT_TRANSACTIONS ON --启动隐式事务模式
GO
--第一个事务由INSERT语句启动
INSERT INTO imp_tran VALUES('01','Zhang')
INSERT INTO imp_tran VALUES('02','Wang')
COMMIT TRANSACTION --提交第一个隐式事务
GO
--第二个隐式事务由SELECT语句启动
SELECT COUNT(*)
FROM imp_tran
INSERT INTO imp_tarn VALUES('03','Li')
COMMIT TRANSACTION --提交第二个隐式事务
GO
SET IMPLICIT_TRANSACTIONS OFF --关闭隐式事务模式
GO

2.2 事务回滚(Transaction Rollback)
当事务执行过程种遇到错误时,该事务修改所有数据都恢复到事务开始的状态或某个制定位置,事务占用的资源将被释放。
语法格式:
ROLLBACK [ TRAN [ SACTION ]
[ transaction_name | @tran_name_variable
| savepoint_name | @savepoint_variable ] ]

参数
transaction_name
是给 BEGIN TRANSACTION 上的事务指派的名称。transaction_name 必须符合标识符规则,但只使用事务名称的前 32 个字符。嵌套事务时,transaction_name 必须是来自最远的 BEGIN TRANSACTION 语句的名称。
@tran_name_variable
是用户定义的、含有有效事务名称的变量的名称。必须用 char、varchar、nchar 或 nvarchar 数据类型声明该变量。
savepoint_name
是来自 SAVE TRANSACTION 语句的 savepoint_name。savepoint_name 必须符合标识符规则。当条件回滚只影响事务的一部分时使用 savepoint_name。
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名称。必须用 char、varchar、nchar 或 nvarchar 数据类型声明该变量。

如果要让事务回滚到指定位置,则需要在事务种设定保促点(SavePoint),所谓保存点是指定其所在位置之前的事务语句,不能回滚的语句即此语句前面的操作被视为有效的。
可以使用 SAVE TRANSACTION savepoint_name 语句创建一个保存点,然后再执行 ROLLBACK TRANSACTION savepoint_name 语句回滚到该保存点,从而无须回滚到事务的开始。
在不可能发生错误的情况下,保存点很有用。在很少出现错误的情况下使用保存点回滚部分事务,比让每个事务在更新之前测试更新的有效性更为有效。更新和回滚操作代价很大,因此只有在遇到错误的可能性很小,而且预先检查更新的有效性的代价相对很高的情况下,使用保存点才会非常有效

eg:
CREATE TRIGGER tri_uptab ON goods
FOR UPDATE
AS
SAVE TRANSACTION tran_uptab
INSERT INTO newgoods
SELECT *
FROM inserted
IF(@@error<>0)
BEGIN
ROLLBACK TRANSACTION tran_updat
END
本例将事务与触发器结合起来实现数据的完整性。触发器tri_uptab内部是一个自动提交事务,用户使用SAVE TRANSACTION tran_uptab 语句完成部分回滚到保存点tran_updab,避免ROLLBACK TRANSACTION 语句回滚到最远的BEGIN TRANSACTION语句。回滚的操作由IF 语句控制,只有当INSERT操作不能成功完成,才进行回滚。否则,触发器tri_uptab中的事务被自动提交。

2.3事务嵌套
eg:
CREATE TABLE employee_tran
(num char(2) NOT NULL,
cname char(6) NOt NULL)
GO
BEGIN TRANSACTION Tran1 --@@TARNCOUNT为1
INSERT INTO emplyee_tran VALUES('01','Zhang')
BEGIN TRANSACTION Tran2 --2
INSERT INTO employee_tran VALUES('02','Wang')
BEGIN TRANSACTION Tarn3 --3
PRINT @@TRANCOUNT
INSERT INTO employee_tran VALUES('03','Li')
COMMIT TRANSACTION Tran3 --@@TRANCOUNT为2
PRINT @@TRANCOUNT
COMMIT TRANSACTION Tran2 --1
PRINT @@TRANCOUNT
COMMIT TRANSACTION Tran1 --0
PRINT @@TRANCOUNT

该例生成三个级别的嵌套事务,然后提交该嵌套事务。SQL Server忽略提交目内部事务。根据最外层事务结束时采取的操作,将事务提交或是回滚。如果提交外部事务,则内层嵌套的事务也会提交,如果回滚外部事务,则不论此前是否单独提交过内层事务,所有内层事务都将回滚。@@TRANCOUNT返回当前共有多少个事务在处理中。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值