SQLSERVER-事务笔记

--【一】
--为什么需要事务?
--假如有两个金额账户A和B,A账户有500元,B账户有2000元。现在要将A账户里的500元转账给B账户。但有个条件约束,设定为账户金额不能小于1.
--执行语句如下:
--UPDATE BANK SET MONEY=MONEY-500 WHERE NAME='A'
--UPDATE BANK SET MONEY=MONEY+500 WHERE NAME='B'
--在执行以上语句的时候,会因为A账户的金额减少500等于0而被终止语句,便B账户却会多出500元,这样,在银行的总账户里就会多出500元,也就是银行亏损了500元


--为了保证执行语句的完整性,将要使用事务




--事务的概念以及特性
/*
事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作
多个操作作为一个整体向系统提交,要么都执行,要么都不执行
事务是一个不可分割的工作逻辑单元


转账过程就是一个事务


它需要两条UPDATE语句来完成,这两条语句是一个整体
如果其中任何一条出现错误,则整个转账业务也应取消
两个账户中的余额应恢复到原来的数据
从而确保转账前和转账后的余额不变
*/


--【二】
--事务的特性
/*
事务必须具备以下四个属性,简称ACID属性:
原子性(Atomicity)
事务是一个完整的操作,事务的各步操作是不可分的(原子的);要么都执行,要么都不执行


一致性(Consistency)
当事务完成时,数据必须处于一致状态


隔离性(Lsolation)
张三和李四之间的转账与王五和赵二之间的转账,永远是相互独立的。(并发事务之间相互独立)


永久性(Durability)
事务完成后,它对数据库的修改被永久保存
*/


--【三】
/*
开始事务 BEGIN TRANSACTION
提交事务 COMMIT TRANSACTION
回滚(撤消)事务 ROLLABCK TRANSACTION


一旦事务提交或回滚,则事务结束
操作步骤:
1)BEGIN TRAN
2)声明变量用于累加错误号,错误号使用全局变量@@ERROR
3)为2)中声明的变量赋初始值为0
4)增、删、改的T-SQL语句
5)SET @变量=@变量+@@ERROR --累计错误号


重复4)、5)直到所有的业务完成
6)使用IF...ELSE判断累加的错误号是否>0,大于就回滚,否则就提交
*/


USE E_Market
GO
--查看转发之前的全额
SELECT * FROM BANK
GO


--开始事务,从此处开始,后续的T-SQL语句是一个整体
--【1、开始事务】
BEGIN TRAN
--【2、定义变量,用于累计事务执行过程中的错误】
DECLARE @error int 
--【3、给该变量赋值】
SET @error=0  --set一般用来变量赋值,select一般将查询出来的值赋给变量
--【4、开始执行转账】
UPDATE BANK SET MONEY=MONEY-500 WHERE NAME='A'
--【5、累加错误】
SET @error=@error+@@ERROR
--重担执行步骤4、5
UPDATE BANK SET MONEY=MONEY+500 WHERE NAME='B'
SET @error=@error+@@ERROR


--【6、使用IF...ELSE去判断累加的错误号,确定事务是提交是回滚】
IF (@error>0)
BEGIN
PRINT'交易失败!回滚事务'
ROLLBACK TRAN
END
ELSE
BEGIN
PRINT'交易成功,提交事务,写入硬盘'
COMMIT TRAN
END
GO


--【三】
-- 嵌套事务及事务分类
/*
.全局变量@@TRANCOUNT,返回当前连接的活动事务数量


.显示事务,用BEGIN TRANSACTION明确指定事务的开始最常用的事务类型


.隐性事务,通过设置SET IMPLICIT_TRANSACTIONS ON语句,将隐性事务模式设置为打开
其后的T-SQL语句自动启动一个新事务
提交或回滚一个事务后,下一个T-SQL语句又将启动一个新事务


.自动提交事务
SQL SERVER 的默认模式
每条单独的T-SQL语句将视为一个事务
*/


-- COMMIT提交,对事务的影响(使用嵌套事务)
PRINT @@TRANCOUNT --在没有事务的时候,查看一下事务数量
BEGIN TRAN --开始第一个事务
PRINT @@TRANCOUNT --开始事务,@@TRANCOUNT将被置为1


BEGIN TRAN --开始第二个事务
PRINT @@TRANCOUNT --事务数+1 


COMMIT TRAN --提交第二个事务
PRINT @@TRANCOUNT --事务数-1


COMMIT TRAN --提交第一个事务,事务数-1
PRINT @@TRANCOUNT


GO


-- ROLLBACK回滚,对事务数量的影响
PRINT @@TRANCOUNT --在没有事务的时候,查看一下事务数量
BEGIN TRAN --开始第一个事务
PRINT @@TRANCOUNT --开始事务,@@TRANCOUNT将被置为1


BEGIN TRAN --开始第二个事务
PRINT @@TRANCOUNT --事务数+1 


ROLLBACK TRAN --回滚事务将清零,所有活动事务都将回滚
PRINT @@TRANCOUNT


GO


--显示事务
USE E_Market
GO
SET NOCOUNT ON --设置不显示受影响行数(不是本章知识点,可忽略)


--设置为显示事务模式
SET IMPLICIT_TRANSACTIONS OFF
GO
PRINT'开始事务数:'+CAST(@@TRANCOUNT AS VARCHAR(10))
GO
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE NAME='Table1')
DROP TALBE Table1
GO
CREATE TALBE TABLE1
(
COL1 INT
)
-- 向表中插入一条数据
INNSERT INTO TABLE1 VALUES(1)
PRINT'使用显示事务数量为:'+CAST(@@TRANCOUNT AS VARCAHR(10))
BEGIN TRAN
PRINT '显示事务的个数:'+CAST(@@TRANCOUNT AS VARCAHR(10))
COMMIT TRAN --提交事务
GO
PIRNT '显示事务的个数是:'+CAST(@@TRANCOUNT AS VARCHAR(10))
GO


--结果为:通过【SET IMPLICIT_TRANSACTIONS OFF】关闭隐式事务,在向数据库插入一条信息的时候,所以事务数是0.在通过begin创建事务后,显示事务数为1.提交事务后,整数务变为0




--设置为隐式事务模式
PRINT '设置为隐式事务模式'
SET IMPLICIT_TRANSACTIONS ON --显启隐式开启
INNSERT INTO TABLE1 VALUES(2)
PRINT '使用事务数:'+CAST (@@TRANCOUNT AS VARCHAR(10))
COMMIT TRAN --提交事务,如果不提交,将在执行下面任意一条语句中自动开启下一个事务,包括所有的CREATE,TRUNCATE TABLE,INSERT,SELECT,ALTER TABLE,GRANT,UPDATE,所有的DROP,ROVOK,DELETE都将自动开启下一个事务
PRINT '显示提交后的事务数量:'+CAST(@@TRANCOUNT AS VARCHAR(10))
GO
--结果:由于开启了隐式模式,在插入语句的时候,将自动创建一个事务,事务数为1




--自动提交事务
--当设置IMPLICIT_TRANSACTIONS OFF (也就是显示模式的时候,就开启了自动提交模式)
SET IMPLICIT_TRANSACTIONS OFF --设置为显示事务模式,也就是恢复成了自动提交模式
INNSERT INTO TABLE1 VALUES(3) --如果没有错误,直接提交 
PRINT @@TRANCOUNT --事务数为0


INNSERT INTO TABLE1 VALUES (5,4) --这里会出现错误,会自动回滚
PRINT @@TRANCOUNT --事务数为0,由于已经回滚,事务数也是0


--【四】
--事务的相关问题
/*
对数据库的操作方式分为串行方式与并发方式
事务并发所产生的问题
.数据丢失更新:两个事务同时一组数据项更新,导致后面的更新覆盖前面的更新
.读脏数据:一个事务正在读另一个更新事务沿未提交的数据
.不可重复读:当一个事务读取某一数据后,另一事务对该数据执行新操作,使得第一个事务无法再次读取与前一次相同的结果。

解决并发事务的问题的解决方案--封锁
共享锁:一个数据对象上已存在共享锁时,其他事务可以读取数据,但不能修改数据
排他锁:它所锁定的资源,其他事务不能读取也不能修改
更新锁:在修改操作的初始化阶段用来锁定可能要被修改的资源
意向锁:意向锁表示一个事务为了访问数据库对象放置在资源层次结构的一个级别上的锁,以保护较低级别资源上的共享或排它锁。


隔离级别:
未授权读取:允许读取脏数据,但不允许更新丢失,如果一个事务已经开始写数据,则允许其他事务读此数据,但不允许同时进行写操作
授权读取:读取数据的事务允许其他并行事务访问该数据,但是未提交的写事务将禁止其他事务和轴时访问该数据
可重复读取:禁止不可重复读和读脏数据,但有时可能出现幻读数据。
序列化:它要求事务序列化执行,即事务只能一个接着一个地执行。
*/









猜你喜欢

转载自blog.csdn.net/weixin_38486884/article/details/79063511