事务的特性,事务的隔离级别和传播行为,为什么要有隔离级别

事务(Transaction)概念:一个sql语句就是一个事务,事务可以保证一组sql语句要么都成功,要么都失败。

事务,就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。

如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。

当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。

由于其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。

特性

1. 原子性:一个事务中的所有语句,应该做到:要么全执行要么一个都不执行;

2. 一致性:让数据保持逻辑上的合理性。比如一个商品出库时,既要让商品库中的该商品数量减一,又要让对应用户的购物车中的该商品加一;

事物的执行使得数据库从一种正确状态转换成另外一种正确状态;

3. 隔离性:如果多个事务同时并发执行,但每个事务就像各自独立执行一样。在事物正确提交之前,不允许把事物对该数据的改变提供给任何其他事物,即在事物正确提交之前,它可能的结果不应该显示给其他事物。

4. 持久性:一个事务执行成功,则对数据来说,应该是一个明确的硬盘数据更改(而不仅仅是内存中的变化)

事物正确提交之后,其结果将永远保存在数据库之中,即使在事物提交之后有了其他故障,事物的处理结果也会得到保存。

作用

事物管理对于企业级应用而言至关重要,它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自动提款机ATM,通常ATM都可以正常为客户服务,但是也难免遇到操作过程中及其突然出故障的情况,此时,事物就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过ATM机一样,以保证用户和银行的利益都不受损失。

并发下事物会产生的问题

举个例子,事物A和事物B操纵的是同一个资源,事物A有若干个子事物,事物B也有若干个子事物,事物A和事物B在高并发的情况下,会出现各种各样的问题。"各种各样的问题",总结一下主要就是五种:第一类丢失更新、第二类丢失更新、脏读、不可重复读、幻读。五种之中,第一类丢失更新、第二类丢失更新不重要,不讲了,讲一下脏读、不可重复读和幻读。

1、脏读

所谓脏读,就是指事物A读到了事物B还没有提交的数据,比如银行取钱,事物A开启事物,此时切换到事物B,事物B开启事物-->取走100元,此时切换回事物A,事物A读取的肯定是数据库里面的原始数据,因为事物B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读。

2、不可重复读

所谓不可重复读,就是指在一个事物里面读取了两次某个数据,读出来的数据不一致。还是以银行取钱为例,事物A开启事物-->查出银行卡余额为1000元,此时切换到事物B事物B开启事物-->事物B取走100元-->提交,数据库里面余额变为900元,此时切换回事物A,事物A再查一次查出账户余额为900元,这样对事物A而言,在同一个事物内两次读取账户余额数据不一致,这就是不可重复读。

3、幻读

所谓幻读,就是指在一个事物里面的操作中发现了未被操作的数据。比如学生信息,事物A开启事物-->修改所有学生当天签到状况为false,此时切换到事物B,事物B开启事物-->事物B插入了一条学生数据,此时切换回事物A,事物A提交的时候发现了一条自己没有修改过的数据,这就是幻读,就好像发生了幻觉一样。幻读出现的前提是并发的书屋中有失误发生了插入、删除操作。

为什么要有隔离级别

事物隔离级别,就是为了解决上面几种问题而诞生的。为什么要有事物隔离级别,因为事物隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大,因此很多时候必须在并发性和性能之间做一个权衡。所以设立了几种事物隔离级别,以便让不同的项目可以根据自己项目的并发情况选择合适的事物隔离级别,对于在事物隔离级别之外会产生的并发问题,在代码中做补偿。

事物隔离级别有4种,但是像Spring会提供给用户5种,来看一下:

1、DEFAULT

默认隔离级别,每种数据库支持的事物隔离级别不一样,如果Spring配置事物时将isolation设置为这个值的话,那么将使用底层数据库的默认事物隔离级别。顺便说一句,如果使用的MySQL,可以使用"select @@tx_isolation"来查看默认的事物隔离级别

2、READ_UNCOMMITTED

读未提交,即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种,因此很少使用

3、READ_COMMITED

读已提交,即能够读到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读

4、REPEATABLE_READ

重复读取,即在数据读出来之后加锁,类似"select * from XXX for update",明确数据读取出来就是为了更新用的,所以要加一把锁,防止别人修改它。REPEATABLE_READ的意思也类似,读取了一条数据,这个事物不结束,别的事物就不可以改这条记录,这样就解决了脏读、不可重复读的问题,但是幻读的问题还是无法解决

5、SERLALIZABLE

串行化,最高的事物隔离级别,不管多少事物,挨个运行完一个事物的所有子事物之后才可以执行另外一个事物里面的所有子事物,这样就解决了脏读、不可重复读和幻读的问题了

网上专门有图用表格的形式列出了事物隔离级别解决的并发问题:


再必须强调一遍,不是事物隔离级别设置得越高越好,事物隔离级别设置得越高,意味着势必要花手段去加锁用以保证事物的正确性,那么效率就要降低,因此实际开发中往往要在效率和并发正确性之间做一个取舍,一般情况下会设置为READ_COMMITED,此时避免了脏读,并发性也还不错,之后再通过一些别的手段去解决不可重复读和幻读的问题就好了。

spring七个事务传播属性

1.PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

2.PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。

3.PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。

4.PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。

5.PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6.PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。

7.PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

备注:常用的两个事务传播属性是1和4,即PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW

关键词:

1)虚读(幻读):在一个事务内读取了别的事务插入的数据,导致前后读取不一致(insert),事务1读取记录时事务2增加了记录并提交,事务1再次读取时可以看到事务2新增的记录;

2)不可重复读取:在一个事务内读取表中的某一行数据,多次读取结果不同.一个事务读取到了另一个事务提交后的数据.事务1读取记录时,事务2更新了记录并提交,事务1再次读取时可以看到事务2修改后的记录;

3)脏读:指一个事务读取了一个未提交事务的数据事务1更新了记录,但没有提交,事务2读取了更新后的行,然后事务T1回滚,现在T2读取无效。





  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值