sqlserver 事务

一、实际问题

问:怎么保证两条SQL语句同时执行成功或者同时执行失败?

答:使用事务来保证。

二、举例说明

---例子:一个人要给另一人转账,假设0001号用户只有100块钱,0002号用户有50块钱

-- bank表字段cid、balance

--  从 0002用户减去100元>50元,显然是要出错,钱不会减少。
  update bank set balance=balance-100 where cid='0002'

-- 给0001用户增加100元,但是0001用户缺神奇的多了100元!

  update bank set balance=balance + 100 where cid='0001'

--  如果sql语句执行过程中一条失败了另一条成功了,那银行就很糟糕!

--解决:通过把两个sql语句放到一个事务里,如果任何一条语句发生失败,会回滚到事务内SQL语句执行前的状态。

--步骤:

  --1.打开一个事务

  begin transaction

  declare @sum int =0

  --2 执行SQL语句

  update bank set balance=balance-100 where cid='0002'

  set @sum=@sum+@@error  ----在转账之前最好通过if-else判断,不要让程序发生异常或者错误!

  update bank set balance=balance + 100 where cid='0001'

  set @sum=@sum+@@error

  --3 判断,如果有任何一条SQL语句执行出错,那么@@error就不会返回0

  if @sum<>0  

  begin

    rollback  --4失败则回滚

  end

  else

    begin 

  commit  --5成功,则提交

  end

--注意:实际工作中杜绝抛出异常,要把所有的异常都判断到,消灭在if-else中。

三、事务类型:

  --1全自动提交事务

  --当执行一条sql语句的时候,数据库自动帮我们打开一个事务,当语句执行成功,数据库自动提交事务,执行失败,数据库自动回滚事务。

    --insert into bbbb values(fsd) --这条sql语句内部实际就有一个事务。

  --2隐式事务,每次执行一条sql语句的时候,数据库自动帮我们打开一个事务,但是需要我们手动提交事务,或者回滚事务。

    SET IMPLICIT_TRANSACTIONS { ON | OFF }隐式事务

    --打开隐式事务 :自动打开事务,手动提交或回滚事务

    SET IMPLICIT_TRANSACTIONS ON

    insert into bank values('0003',1000000)

    commit

    SET IMPLICIT_TRANSACTIONS off

  --3显示事务:需要手动打开事务,手动提交事务或者回滚事务。

      begin tran --...... commit tran --- rollback transaction ------(如上面的例子)

 四、事务的特性

事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性,称为原子性、一致性、隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务。
1原子性
  事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
2一致性
  事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。
3隔离性
  由并发事务所作的修改必须与任何其他并发事务所作的修改隔离。事务识别数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是第二个事务修改它之后的状态,事务不会识别中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
4持久性
  事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。

 

posted @ 2017-12-12 00:03  hao_1234_1234  阅读(236)  评论(0编辑  收藏  举报