事务
为什么需要事务
分析银行转账流程:资金从账户A转到账户B,至少需要两步
-
账户A的资金减少
-
账户B的资金对应增加
问题是:有可能转账资金不足或者资金冻结等一系列问题
UPDATE [User] SET CurrentMoney-=100 WHERE ID=11004
UPDATE [User] SET CurrentMoney+=100 WHERE ID=11005
分析问题:
-
11004号账户转出资金失败-UPDATE语句违反检查约束
-
但是11005号账户转入资金成功
-
结果导致银行亏钱
什么是事务
事务的概念及要求
-
事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作
-
多个操作作为一个整体向系统提交,要么全部执行,要么都不执行
-
事务是一个不可分割的工作逻辑单元
银行转账过程就是一个事务
-
它需要两条UPDATE语句来完成,这两条SQL语句是一个整体
-
如果其中任意一条出现异常,则整个转账业务也应该取消,两个账户中的余额应该恢复到原来的数据,从而确保转账前和转账后的余额不变
事务的特性
ACID
-
原子性(Atomicity):事务是一个完整的操作,事务的各个步骤的操作都是不可分的,要么都执行,要么都不执行
-
一致性(Consistency):当事务完成时,数据必须处于一致状态
-
隔离性(Isolation):并发事务之间彼此隔离,独立。它不应该以任何方式依赖于或影响到其他事务
-
永久性(Durability):事务完成后,它对数据库的修改被永久保存
事务的分类
显示事务
-
用BEGIN TRANSACTION明确指定事务的开始
-
最常用的事务类型
隐式事务
-
通常会设置SET IMPLICIT_TRANSACTIONS ON语句将隐式事务模式设置为打开
-
其后的T-SQL语句会自动启动一个新事务
-
提交或回滚一个事务后,下一个T-SQL语句又将启动 一个新事务
自动提交事务
-
SQL Server的默认模式
-
每条单独的T-SQL语句可理解为一个事务
创建事务
--银行转账业务
DECLARE @ZHA INT=11004,@ZHB INT=11005,@Money INT=10,@errorSum INT=0
BEGIN TRANSACTION
BEGIN
UPDATE [User] SET CurrentMoney-=@Money WHERE ID=@ZHA
SET @errorSum+=@@ERROR --对错误进行累计
UPDATE [User] SET CurrentMoney+=@Money WHERE ID=@ZHB
SET @errorSum+=@@ERROR
IF(@errorSum>0)
BEGIN
PRINT '转账失败!'
ROLLBACK TRANSACTION ---事务回滚
END
ELSE
BEGIN
PRINT '转账成功!'
COMMIT TRANSACTION ----事务提交
END
END
-
开始事务
BEGIN TRAN[SACTION]
-
提交事务
COMMIT TRANSACTION
-
回滚事务(撤销事务)
ROLLBACK TRANSACTION
一旦事务被提交或者被回滚,则该事务都结束
事务处理中的关键问题
对事务中的INSERT、UPDATE、DELETE语句实时跟踪
判断某条语句执行是否出错的方法
-
使用全局变量@@ERROR
-
@@ERROR只判断当前一条T-SQL语句执行是否有错
-
为了判断事务中所有T-SQL语句是否有错,可以对错误进行累计
事务的使用
CREATE PROC sp_BankZhuanZhang
@ZHA INT,
@ZHB INT,
@Money INT
AS
DECLARE @errorSum INT=0
BEGIN TRAN
BEGIN
UPDATE [User] SET CurrentMoney-=@Money WHERE ID=@ZHA
SET @errorSum+=@@ERROR
UPDATE [User] SET CurrentMoney+=@Money WHERE ID=@ZHB
SET @errorSum+=@@ERROR
IF(@errorSum>0)
BEGIN
PRINT '转账失败!'
ROLLBACK TRANSACTION ---事务回滚
END
ELSE
BEGIN
PRINT '转账成功!'
COMMIT TRANSACTION ----事务提交
END
END