1.事务的概念
事物是一种机制,是一种操作序列,它包含了数据库一组操作命令,这组命令要么全部执行,要么都不执行。因此事物是一组不可分割的事物逻辑单元,在数据库进行并发操作时候,事物是作为最小的控制单元来使用的,这特别适用于多用户同时操作的数据通信系统。例如:订票、银行、保险公司以及证券交易系统等。
2.事物的4大属性
- 原子性:事物是一个完整的操作;
- 隔离性:对数据进行修改的所有并发事物都是彼此隔离的;
- 一致性:当事物完成时,事物必须处于一致的状态;
- 持久性:事物完成后,对于系统的影响是永久的;
3.创建事物
- 开始事物:transaction begin
- 提交事物:commit transaction
- 回滚事物:rollback transaction
4.事物的分类
- 显示事物:用begin transaction 明确指定事物的开始,用commit transaction, rollback transaction来结束或者回滚事务
- 隐示事物(自动提交事物):隐式事务则在执完语句后自动提交事务
5.事例
实现转账操作,转账人出账和收账人入账是一组完整的操作序列,必须全部完成或不完成,准备一张用户钱包表(tbUserWallet),转账交易记录表(tbTransaction),简单设计如下
向用户钱包表(tbUserWallet)添加测试数据
创建转账存储事物
USE [TEST] GO /****** Object: StoredProcedure [dbo].[pAddTransaction] Script Date: 2018/5/21 12:44:59 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: yangyi -- Create date: 18/05/21 -- Description: 转账 -- ============================================= CREATE PROCEDURE [dbo].[pAddTransaction] @InOpenID uniqueidentifier, @InTDesc nvarchar(50), @OutOpenID uniqueidentifier, @OutTDesc nvarchar(50), @TAmount decimal(10, 2), @TTID int, @Result int output AS BEGIN IF((SELECT Amount FROM tbUserWallet WHERE OpenID=@OutOpenID)>=@TAmount) BEGIN BEGIN TRANSACTION BEGIN TRY UPDATE tbUserWallet SET Amount=Amount-@TAmount WHERE OpenID=@OutOpenID UPDATE tbUserWallet SET Amount=Amount+@TAmount WHERE OpenID=@InOpenID --SELECT 1+'A' INSERT INTO [dbo].[tbTransaction]([TID],[OpenID],[TAmount],[TTID],[TDesc],[CreateDT])VALUES(NEWID(),@InOpenID,@TAmount,@TTID,@InTDesc,GETDATE()) INSERT INTO [dbo].[tbTransaction]([TID],[OpenID],[TAmount],[TTID],[TDesc],[CreateDT])VALUES(NEWID(),@OutOpenID,-@TAmount,@TTID,@OutTDesc,GETDATE()) END TRY BEGIN CATCH IF(@@TRANCOUNT>0) BEGIN SET @Result=-1 PRINT '事物执行出错,回滚' ROLLBACK TRANSACTION END END CATCH IF(@@TRANCOUNT>0) BEGIN SET @Result=1 PRINT '一切按预期计划执行' COMMIT TRANSACTION END END ELSE BEGIN PRINT '转账人金额不足' SET @Result=0 END END GO
测试1>:转账人金额不足测试
USE [TEST] GO DECLARE @return_value int, @Result int EXEC @return_value = [dbo].[pAddTransaction] @InOpenID = '1ccd524d-de62-47ca-87d3-38787b040ba3', @InTDesc = N'收到A的转账100', @OutOpenID = '2ccd524d-de62-47ca-87d3-38787b040ba3', @OutTDesc = N'转账给A100', @TAmount = 100, @TTID = 1, @Result = @Result OUTPUT SELECT @Result as N'@Result' GO
测试2>:模拟事物出现错误,进行回滚
取消存储事物中的:SELECT 1+'A' 注释(模拟事物中发生错误)
USE [TEST] GO DECLARE @return_value int, @Result int EXEC @return_value = [dbo].[pAddTransaction] @InOpenID = '2ccd524d-de62-47ca-87d3-38787b040ba3', @InTDesc = N'收到A的转账100', @OutOpenID = '1ccd524d-de62-47ca-87d3-38787b040ba3', @OutTDesc = N'转账给A100', @TAmount = 100, @TTID = 1, @Result = @Result OUTPUT SELECT @Result as N'@Result' GO
测试3.>执行成功测试,注释 SELECT 1+'A'
USE [TEST] GO DECLARE @return_value int, @Result int EXEC @return_value = [dbo].[pAddTransaction] @InOpenID = '2ccd524d-de62-47ca-87d3-38787b040ba3', @InTDesc = N'收到A的转账100', @OutOpenID = '1ccd524d-de62-47ca-87d3-38787b040ba3', @OutTDesc = N'转账给A100', @TAmount = 100, @TTID = 1, @Result = @Result OUTPUT SELECT @Result as N'@Result' GO