专栏首页Java架构沉思录一文读懂数据库事务
原创

一文读懂数据库事务

什么是事务

根据维基百科的定义,一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的:1)为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法;2)当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。简单来讲,事务的作用至少有两个:保证数据一致性,以及对数据进行隔离。这么说大家可能还不太好理解,我们还是举个例子说明一下吧。

我们以A向B转账100块钱为例,在一笔转账操作中,至少必须包含2个操作:

  1. 将A的账户余额扣除100块钱(假设转账前A的账户余额大于100块钱)
  2. 将B的账户余额增加100块钱

如果在转账的过程中不使用事务,那么有可能会出现在将A的账户扣除100块钱之后,发生了不可预知的异常(比方说服务器宕机了),导致没来得及将B的账户增加100块钱,如此一来,数据库就产生了数据不一致的情况,即A的账户扣了100块钱,但是B的账户并没有相应地增加100块钱,也就是说有100块钱“不翼而飞”了。而如果将这2个操作放在一个事务里执行的话,由于事务中的操作要么全部执行,要么全部不执行,所以可以保证数据一致性。这就是在数据一致性要求比较高的场景下使用事务的好处。

事务的特性

事务的特性主要有4个:原子性,一致性,隔离性与持久性,也叫做ACID。

  1. 原子性,指的是一个事务必须被视为一个不可分割的最小工作单元,整个事务中的操作要么全部提交成功,要么全部失败回滚,也就是说不可能只执行事务中的部分操作,这就是事务的原子性。
  2. 一致性,指的是事务应确保数据库的状态从一个一致状态转变为另一个一致状态。以上述转账的例子为例,转账后A的账户减少100块钱,B的账户增加100块钱是满足数据一致性的,事务可以保证事务成功提交之后数据库转化为这个状态,如果事务失败回滚了,则还是保持最初的一致性状态,而不会出现上述的A的账户减少100块钱,B的账户没有变化的不一致的中间状态。
  3. 隔离性,指的是多个事务并发执行时,一个事务的执行不应影响其他事务的执行。比如当A向B转账的过程中,B也可以向A转账,这2个事务互不影响,而且通常来讲也是互不可见的(注意,是通常来讲“不可见”,后续讲到事务隔离级别的时候再详述)。
  4. 持久性,指的是已被提交的事务对数据库的修改应该被永久保存在数据库中。这个比较好理解,就是说已成功提交的事务会被永久地保存下来。

事务的隔离级别

前文说到,事务具有隔离性,而且通常来讲,不同事务之间是不可见的,然而现实中的事务隔离性并不都是不可见的,实际上,SQL标准定义了4种事务隔离级别:读未提交,读已提交,可重复读,串行化,下文将逐一讲解。

  1. 读未提交,指的是事务中未提交的修改,对于其他事务而言是可见的,这是隔离性最低的一种级别了。在这种隔离级别下,会出现“脏读”的情况。所谓“脏读”指的是读取到了其他事务未提交的数据。我们以2个事务同时进行为例,因为事务A可以读到事务B的未提交的修改数据,假如说事务B在事务A结束之前因为发生异常而回滚了,那么A读到的事务B的未提交的数据就是“过期”的,如果事务A在这个“过期”数据上进行操作,那势必会造成数据不一致的情况。因此这种隔离级别在实际中很少使用。
  2. 读已提交,指的是一个事务开始时,只能看到其他已经提交的事务对数据所做的修改。这种隔离级别可以防止“脏读”的问题出现。但是这种情况可能会出现“不可重复读”的问题。所谓不可重复读是指,事务A先后2次读到的数据不一致。举个例子,事务A先读到小明的账户余额为100块钱,然后再做了其他操作(假设这些操作没有改变小明的余额),这个时候事务B将小明的账户扣了10块钱,变成90块钱了并提交了,由于事务A可以读到事务B提交的修改数据,所以当事务A执行了其他操作后再读取小明的余额时就变成90块了,因此前后2次读取的数据不一致,故出现了“不可重复读”的问题。
  3. 可重复读,指的是可以避免上述“不可重复读”的情况出现,即它可以保证在同个事务中,先后读到的同一行数据是一致的,然而这种隔离级别下会出现另一个问题,就是“幻象读”。“幻象读”指的是事务A读取到了事务B新增的数据,因此出现了“幻行”。举个例子,事务A一开始查询到小明在1月份一共网购了100次,然后再进行其他操作(假设这些操作没有改变小明的网购记录数),然后事务B插入了一条小明新的网购记录并提交了,接下来事务A再统计出小明的网购记录,变成101次了,出现了“幻行”,也就是出现了“幻象读”。
  4. 串性化,指的是强制事务串行执行,其可以避免“幻象读”的问题出现,这是最严格的隔离级别了。因为串行化需要在发生竞争的数据上加锁,所以并发性能不高,只有在对数据一致性要求非常高且并发度不高的情况下才会考虑使用这种隔离级别。
更多精彩,请关注微信公众号:编程沉思录。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一文读懂数据库事务

    什么是事务 根据维基百科的定义,一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的:1)为数据库操作序列提供了一个从失败中恢复...

    黄泽杰
  • 从一笔金币充值去思考分布式事务

    考虑支付重构的时候,自然想到原本属于一个本地事务中的处理,现在要跨应用了要怎么处理。拿充值订单举个栗子吧,假设:原本订单模块和账户模块是放在一起的,现在需要做服...

    黄泽杰
  • MyBatis 事务管理解析:颠覆你心中对事务的理解!

    1.说到数据库事务,人们脑海里自然不自然的就会浮现出事务的四大特性、四大隔离级别、七大传播特性。

    黄泽杰
  • 如何利用事务消息实现分布式事务?

    一说起事务,容易联想到数据库。我们日常使用事务的场景,绝大部分都是在操作数据库的时候。像 MySQL、Oracle这些主流的关系型数据库,也都提供了完整的事务实...

    王小明_HIT
  • 一文读懂数据库事务

    什么是事务 根据维基百科的定义,一个数据库事务通常包含了一个序列的对数据库的读/写操作。它的存在包含有以下两个目的:1)为数据库操作序列提供了一个从失败中恢复...

    黄泽杰
  • Hibernate中的事务隔离问题(脏读、不可重复读、幻读)

    2)一致性:组成事务的各种操作,要么全部成功,要么全部失败。其中有一个失败,事务无法完成

    用户2409797
  • [spring事务]一篇浅文让你摆脱事务困扰

    原子性(Atomicity):事物是一个不可分割的工作单位,事物中的操作要么都发生,要么都不发生

    星尘的一个朋友
  • Java项目实践,数据访问层事务控制方法总结,保障数据安全

    事务是为解决数据安全操作提出的,事务控制实际上就是控制数据的安全访问,比如,银行转帐业务,账户A要将自己账户上的1000元转到B账户下面,A账户余额首先要减去1...

    用户1289394
  • 关系型数据库的ACID(原子性、一致性、隔离性与持久性)

    Coxhuang
  • 重新学习MySQL数据库6:浅谈MySQL的中事务与锁

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖

扫码关注云+社区

领取腾讯云代金券