事务

事务详解

什么是事务

以后我们系统可能实现一个功能,可能不止操作一张表,比如有多张表。最简单的是汇总表和明细表,比如订单表和订单明细,这是一种一对多的关系。比如添加一条订单,可能就会添加十条明细。如果没有事务,假设添加订单成功,但明细只添加了5条,就会导致数据不正确。

事务:保持逻辑数据一致性与可恢复性,要么全部执行,要么全部不执行,回到原数据状态。

书面解释:事务具有原子性、一致性、隔离性、持久性。

  • 原子性:事务必须是一个自动工作的单元,要么全部执行,要么全部不执行。
  • 一致性:事务结束的时候,所有的内部数据都是正确的。
  • 隔离性:并发多个事务时,各个事务不干涉内部数据,处理的都是另外一个事务处理之前或之后的数据。
  • 持久性:事务提交之后,数据是永久性的,不可再回滚。

SQL Server 中事务的三种类型

  1. 自动提交事务:SQL Server 默认的事务模式,每条 Sql 语句都被看成一个事务进行处理。
  2. 显式事务:T-SQL 标明,由 Begin Transaction 开启事务开始,由 Commit Transaction 提交事务、Rollback Transaction 回滚事务结束。
  3. 隐式事务:使用 Set IMPLICIT_TRANSACTIONS ON 将隐式事务模式打开,不用 Begin Transaction 开启事务,当一个事务结束,这个模式会自动启用下一个事务,只用 Commit Transaction 提交事务、Rollback Transaction 回滚事务即可。

不使用事务的情况

-- 清空表数据
delete from guest

-- 插入三条记录
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张一',1,GETDATE()) -- 正确
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张二','二',GETDATE()) -- 错误,下面的脚本不会执行
INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张三',3,GETDATE()) -- 正确

-- 查找
select * from guestCode language: JavaScript (javascript)

使用事务的例子(有错误时回滚)

-- 清空表数据
delete from guest

-- 插入三条记录
begin tran -- 开启事务
begin try
	INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张一',1,GETDATE()) -- 正确
	INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张二','二',GETDATE()) -- 错误,下面的脚本不会执行
	INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张三',3,GETDATE()) -- 正确
end try
begin catch
    -- 出错就会到达这里
    -- 执行失败 输出错误信息
    select Error_number() as ErrorNumber,  -- 错误代码
         Error_severity() as ErrorSeverity,  -- 错误严重级别
         Error_state() as ErrorState ,  -- 错误状态码
         Error_Procedure() as ErrorProcedure , -- 出现错误的存储过程或触发器的名称
         Error_line() as ErrorLine,  -- 发生错误的行号
         Error_message() as ErrorMessage  -- 错误的具体信息
    -- 因为出错了,恢复数据,回滚事务
    if(@@TRANCOUNT>0)
		rollback tran
end catch

if(@@TRANCOUNT>0)
    commit tran

-- 查找
select * from guestCode language: JavaScript (javascript)

所有都成功的情况

-- 清空表数据
delete from guest

-- 插入三条记录
begin tran -- 开启事务
begin try
	INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张一',1,GETDATE()) -- 正确
	INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张二',2,GETDATE()) -- 正确
	INSERT INTO [dbo].[Guest]([name],[age],[createtime]) VALUES('张三',3,GETDATE()) -- 正确
end try
begin catch
    -- 出错就会到达这里
    if(@@TRANCOUNT>0)
		rollback tran
end catch

if(@@TRANCOUNT>0)
    commit tran

-- 查找
select * from guestCode language: JavaScript (javascript)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注