前言

    在做项目的过程中,有时同一个操作会同时对数据库中的两张表进行操作,比如在机房收费系统中,下机需要把下机记录更新到下机表中,同时又要更新卡表中的余额,如果在操作数据库的过程中出现错误,只对其中的某一张表进行了操作,这样就会导致数据不一致。这时候事务就派上大用场了。

定义

    事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作系列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据的一致性。例如银行转账工作,从一个账号扣款并使一个账号增款,这两个操作要么都执行,要么都不执行。所以,应该把他们看成一个事务。

性质

原子性(Atomic):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成功,要么全部失败。

一致性(Consistency):只有合法的数据可以被写入数据库,否则事务应该回滚到最初状态。

隔离性(Isolation):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。

持久性(Durability):事务完成之后,它对于系统的影响是永久的,真是修改了数据库。

语法

BEGIN  TRAN:开始事务,设置事务的起始点。

COMMIT  TRAN:提交事务,使事务成为数据库中永久的、不可逆转的一部分。

ROLLBACK  TRAN:回滚事务,放弃事务中对数据库所做的修改。

SAVE TRAN:设置事务的保存点。

实例

BEGIN TRAN Tran_Money    --开始事务

DECLARE @tran_error int;
SET @tran_error = 0;
    BEGIN TRY 
        UPDATE tb_Money SET MyMoney = MyMoney - 30 WHERE Name = '路人甲';
        SET @tran_error = @tran_error + @@ERROR;
        --测试出错代码,看看路人甲的钱减少,路人乙的钱是否会增加
        --SET @tran_error = 1;
        UPDATE tb_Money SET MyMoney = MyMoney + 30 WHERE Name = '路人乙';
        SET @tran_error = @tran_error + @@ERROR;
    END TRY

BEGIN CATCH
    PRINT '出现异常,错误编号:' + convert(varchar,error_number()) + ',错误消息:' + error_message()
    SET @tran_error = @tran_error + 1
END CATCH

IF(@tran_error > 0)
    BEGIN
        --执行出错,回滚事务
        ROLLBACK TRAN;
        PRINT '转账失败,取消交易!';
    END
ELSE
    BEGIN
        --没有异常,提交事务
        COMMIT TRAN;
        PRINT '转账成功!';
    END


事务可以设置在程序的代码中,也可以写在数据库的脚本中,下面是一个事务和存储过程结合使用的例子

ALTER PROCEDURE [dbo].[Proc_UpdateGoods]
	@name varchar(30),
	@supportName varchar(30),
	@count varchar(30),
	@price varchar(30),
	@totalPrice varchar(30),
	@note varchar(30),
	@timespan datetime,
	@unit varchar(30)
AS

BEGIN 
	begin tran
	declare @num int
	insert  into T_inputinfo (supportName,name,count,price,totalPrice,note,timespan) values(@supportName,@name,@count,@price,@totalPrice,@note,@timespan)
	SELECT @num= COUNT(name)  FROM T_suppliesinfo where name=@name 
	if(@num=0) insert into T_suppliesinfo (name,count,unit) values(@name,@count,@unit)
	else update T_suppliesinfo set count=count+@count

	if @@error<>0 
	begin
	rollback tran
	return 0
	end
	else
	begin 
	commit tran	
	return 1
	end
End



总结

    学过的理论知识是在概念上的理解,重要的还是需要去实践。