源栈培训:数据库:13-事务

更多
2019年03月28日 14点02分 作者:叶飞 修改

经典例子:银行转账(帮帮币交易)

实际上是两条UPDATE语句:

	UPDATE TRegister SET Balance = Balance + 150 WHERE Id = 1
	UPDATE TRegister SET Balance = Balance - 150 WHERE Id = 6
一旦中间出现故障(比如网络故障/系统断电……),就会造成 Id=1 的用户余额增加而 Id=3 的用户没有减少的情况。

解决的办法就是将上述两条语句放到一个事务中。

BEGIN TRANSACTION        -- 开始事务
UPDATE TRegister SET Balance = Balance + 199 WHERE Id = 1
UPDATE TRegister SET Balance = Balance - 199 WHERE Id = 6       -- 因违法CHECK(Balance>0)约束而报错
COMMIT TRANSACTION       -- 提交事务
然而,SQL SERVER 在失败时并不是都可以自动回滚事务(默认约束和锁超时会让事务一直打开)。所以,我们需要:
SET XACT_ABORT ON | OFF  -- 设置只要有错误(无论级别)就回滚事务
在实际开发中,我们通常采用TRY...CATCH的方式来处理:
BEGIN TRANSACTION
BEGIN TRY
    UPDATE TRegister SET Balance = Balance + 150 WHERE Id = 1
    UPDATE TRegister SET Balance = Balance - 150 WHERE Id = 6
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    IF @@TRANCOUNT>0
        ROLLBACK;
    THROW;
END CATCH

TRY...CATCH(异常捕获):

  • 如果没有任何异常(错误),执行完 TRY块(BEGIN...END)之间的内容
  • 否则,直接从错误行跳到 CATCH 块

THROW(抛出异常):养成习惯,不要catch之后就不处理了……


显式事务

声明了 BEGIN TRANSACTION 的事务就是显式事务。事务从 BEGIN TRANSACTION 开始,至 COMMIT 或 ROLLBACK 结束。

  • 提交(COMMIT):执行所有从BEGIN TRANSACTION 开始的操作,结束事务
  • 回滚(ROLLBACK):撤销所有从BEGIN TRANSACTION 开始的操作,恢复原样


隐式事务

SET IMPLICIT_TRANSACTIONS ON | OFF   -- SQL SERVER 默认是OFF的

不需要声明:BEGIN TRANSACTION。从第一行开始(或者上一个COMMIT或ROLLBACK)就是事务起点,直到COMMIT或ROLLBACK才结束。


自动提交

未声明 BEGIN TRANSACTION 的单个SQL语句,自动的受事务控制。

比如:UPDATE...SET column_1 = x, column_2 = y,不可能只更改了column_1,没更改column_2


作业

用户发布一篇悬赏币若干的求助(TProblem),他(TReigister)的帮帮币(BMoney)也会相应减少,但他的帮帮币总额不能少于0分:请综合使用TRY...CATCH和事务完成上述需求。


事务特性:ACID

原子性(Atomicity):不可再分。

一致性(Consistency):要完成都完成,要不完成都不完成。

隔离性(Isolation):正在执行的事务不能被其他事务干扰。

持久性(Durablity):一旦完成,改变就是永久性的。


事务的嵌套

两种方式记忆/理解:

方式一(记忆):

  • 事务提交时从内到外依次提交
  • 回滚内部事务的同时会回滚到外部事务的起点
  • 回滚外部事务的同时回滚所有已提交的内部事务

方式二(理解):

  • SQL SERVER 并不支持真正意义上的事务嵌套。
  • 在一个已有的事务内设置一个BEGIN TRANSACTION,并不会打开新的事务,只是在“内部事务计数器@@TRANCOUNT”上+1(COMMIT/ROLLBACK就-1)
  • 只有最外层的事务才会真正的提交事务

尤其要注意:事务中的存储过程,里面有没有事务……


为什么事务可以回滚

理解SQL SERVER的执行机制:

  1. 检查缓存:如果缓存中没有数据,从磁盘读取,并存入缓存
  2. 在事务日志中记录更改
  3. CHECKPOINT把被修改的页(dirty page)写入磁盘

事务日志


源栈 数据库 SQL 事务
赞: 0 踩: 0

打赏
已收到打赏的 帮帮币

你的 打赏 非常重要!
为了保证文章的质量,每一篇文章的发布,都已经消耗了作者 1 枚 帮帮币
没有“帮帮币”,作者无法发布新的文章。

全系列阅读
评论 / 0
叶飞的系列文章

源栈培训:ASP.NET全栈开发

飞哥的源栈培训:线上全程直播,免费收看;线下拎包入住,按周计费。本系列收录所有讲义(含视频录播地址)

编程那些事:菜鸟入门

大飞哥倾力之作,面向有意入行IT/开发/编程的初学者,欢迎任何形式的留言建议……

从包工头到程序猿

真实故事,讲述我在家装公司关门之后,如何转行成为一个程序猿的故事。(《折腾》第三卷)

《折腾》(卷一)青涩

时间段:从大学毕业到开始创业。离开青葱校园,涉世之初的那些往事……

《折腾》(卷二)风雨 之(1)工地

我一个完全的门外汉(无论装修还是管理),开始给黎叔装修房子。从踌躅满志,到四处碰壁;从一往直前,到左右为难……

《折腾》(卷二)风雨 之(2)胸怀

作为一个律师,接工程没签合同,被狠狠的坑了一把!年轻人暴烈的想要复仇,黎叔教他一个企业家的胸怀……

《折腾》(卷二)风雨 之(3)渠道

成立了公司,招聘了员工,开始大力的拓展业务,一个接一个的坑,摔倒了又爬起来……

《折腾》(卷二)风雨 之(4)视野

经历残酷现实的磨砺,终于明白:干啥事,都不能闭门造车,人要走出去,开阔视野……

未分类

系统自动生成的未分类系列

一锅大杂烩

从律师到包工头,从码农到写手,读书交友生活创业,各种零零碎碎,乱七八糟……

人人都是程序猿

计算机编程普及课程,视频:https://space.bilibili.com/55410301/#/channel/detail?cid=49491

全部
关键字



帮助

反馈