事务的基本知识点

事务: 它是一些列严密操作动作,要么都操作完成,要么都回滚撤销。

简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。在MySQL中,事务支持是在引擎层实现的。 你现在知道,MySQL是一个支持多引擎的系统,但并不是所有的引擎都支持事务。比如MySQL原生的MyISAM引擎就不支持事务,这也是MyISAM被InnoDB取代的重要原因之一。

事务有 下面几大特性:原子性,一致性,隔离性,持久性。

原子性: 事务最基本的操作单元,要么全部成功,要么全部失败,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性: 事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。

隔离性: 指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

持久性: 指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。

下面我们重点了解一下事务的隔离性

隔离性有四个级别:

  • 读未提交
  • 读已提交
  • 可重复读
  • 串行化

读未提交

  1. 事务A是事务B,事务A未提交的数据,事务B可以读取到。
  2. 这里读取的数据叫做脏数据
  3. 这种隔离级别最低,这种级别一般是理论上存在的,数据库隔离级别一般高于这个级别。

公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高 兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有 2000元,singo空欢喜一场。

img

出现上述情况,即我们所说的脏读 ,两个并发的事务,“事务A:领导给singo发工资”、“事务B:singo查询工资账户”,事务B读取了事务A尚未提交的数据。

读已提交

  1. 事物A和事物B,事物A提交的数据,事物B才能读取到

  2. 这种隔离级别高于读未提交

  3. 换句话说,对方事物提交之后的数据,我当前事物才能读取到

  4. 这种级别可以避免“脏数据”

  5. 这种隔离级别会导致“不可重复读取”

  6. Oracle默认隔离级别

singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在 singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何…

出现上述情况,即我们所说的不可重复读 ,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。

当隔离级别设置为Read committed 时,避免了脏读,但是可能会造成不可重复读。

大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。

可重复读

  1. 事务A和事务B,事务A提交之后的数据,事务B读取不到

  2. 事务B是可重复读取数据

  3. 这种隔离级别高于读已提交

  4. 换句话说,对方提交之后的数据,我还是读取不到

  5. 这种隔离级别可以避免“不可重复读取”,达到可重复读取

  6. 比如1点和2点读到数据是同一个

  7. MySQL默认级别

  8. 虽然可以达到可重复读取,但是会导致“幻像读”

当隔离级别设置为Repeatable read 时,可以避免不可重复读。当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

虽然Repeatable read避免了不可重复读,但还有可能出现幻读 。

singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额 (select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction … ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。

串行化

  1. 事务A和事务B,事务A在操作数据库时,事务B只能排队等待

  2. 这种隔离级别很少使用,吞吐量太低,用户体验差

  3. 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行,而不并发

脏读:读取没有提交的数据

脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOMCoQf3-1575538899394)(C:\Users\ADMINI~1\AppData\Local\Temp\企业微信截图_15755379118763.png)]

不可重复读:(前后多次读取,数据内容不一致)

是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxU8fja4-1575538899394)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20191205173759808.png)]

幻读:(前后多次读取,数据总量不一致)

事务在插入已经检查过不存在的记录时,惊奇的发现这些数据已经存在了,之前的检测获取到的数据如同鬼影一般。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rlBqlIq-1575538899394)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20191205173926538.png)]

不可重复读和幻读到底有什么区别呢?

  1. 不可重复读是读取了其他事务更改的数据,针对update操作
    解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。

  2. 幻读是读取了其他事务新增的数据,针对insert与delete操作
    解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。

幻读和不可重复读都是指的一个事务范围内的操作受到其他事务的影响了。只不过幻读是重点在插入和删除,不可重复读重点在修改
参考:https://www.jianshu.com/p/081a3e208e32

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值