Spring事务(一)-事务回顾

事务回顾

什么是事务?

事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败。

经典案例
张三账户有1000元,李四账户也有1000元。此时,张三要给李四转账200元,这个操作包括如下步骤:
① 修改张三账户,扣除200元
② 修改李四账户,增加200元
只有以上这两步都完成了,才算转账成功。任何一步失败都是不行的,也就是说①和②是存在一个事务中,并且必须满足事务的一系列特性。

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

以上转账步骤①和②要么一起成功,要么一起失败。

② 一致性(Consistency):指事务前后数据的完整性必须保持一致。

张三给李四转账,但是他俩的账户总额保持不变,不能出现张三账户减少200元,李四账户没增加200元的情况。

③ 隔离性(Isolation):指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。

张三的账户在转账的同时,另一个事务也在操作张三的账户,导致数据出现重复操作的情况。

④ 持久性(Durability):指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响。

张三给李四转账完成后,这个结果是永久性的,也就是说张三的账户实实在在的减少了200元,而李四的账户实实在在的增加了200元。

事务所面临的问题

ACID这4大特性当中,其实最难理解的是隔离性。正因为它的难理解,才有了所谓的事务隔离级别。没有隔离性,在高并发下就会产生如下问题:
① 脏读:有两个或多个事务同时修改张三的账户,这样就会产生垃圾数据,导致最终的结果跟实际不符。

时间事务A事务B
T1开始事务
T2开始事务
T3查询余额(1000 元)
T4取出1000元(余额 0 元)
T5查询余额(0 元)
T6撤销事务(余额恢复为 1000 元)
T7存入500元(余额 500 元)
T8提交事务

事务A可以理解为:张三正在向李四转账 500 元
事务B可以理解为:李四自己正在取款 1000 元
这两个操作刚好在同一时段进行:
T1-T4:李四取款时,程序代码肯定是先查询李四的账户余额发现有1000元,然后在1000的基础上减去1000,最终李四账户余额为0元。
T5:此时,正好张三在向李四转账500元,程序代码肯定也是先查询李四的账户,发现余额为0元。
T6:李四在取款过程中出现异常回滚,余额重新恢复到1000元。
T7:张三查询到李四账户余额为0后,程序代码直接执行了0+500=500的操作,然后提交事务,最终得出李四的账户余额为500元。
真实的结果应该是:李四的账户余额为1500元,事务B在回滚时,最新的余额没有通知到事务A,这就导致了事务A在T5时间点读出的数据为脏数据。

② 不可重复读:李四第一次查询自己的账户余额为1000元,然后又重新查询了一次,结果变成了0元。钱莫名其妙的就少了1000元,这让李四非常的郁闷。

时间事务A事务B
T1开始事务
T2开始事务
T3查询余额(1000 元)
T4查询余额(1000 元)
T5取出1000元(余额 0 元)
T6提交事务
T7查询余额(0 元)

T1-T3:事务B查询余额为1000元。
T4:事务A查询余额为1000元。
T5-T6:事务B取出1000元,并且提交了事务。
T7:事务B再次查询了余额,结果变成了0元。尴尬了~~~

③ 幻读:银行工作人员在统计张三的账户总存款时,发现有时候刷新一次,总存款就变得不一样了。

时间事务A(统计总存款)事务B(存款)
T1开始事务
T2开始事务
T3统计总存款(10000元)
T4存入100元
T5提交事务
T6统计总存款(10100元)

T1-T3:事务A统计总存款10000元。
T4-T5:事务B存入100元,提交了事务。
T6:事务A统计总存款10100元。

事务的隔离级别

以上提到的事务在高并发下的三种问题可以用一句话描述:

  • 脏读:事务A读取了事务B未提交的数据,并在这个基础上又做了其他操作。
  • 不可重复读:事务A读取了事务B已提交的更改数据。
  • 幻读:事务A读取了事务B已提交的新增数据。

脏读是坚决抵制的,不可重复读和幻读在大多数情况下能够被接受。
有了以上问题的存在,所以事务的隔离级别就扮演着很重要的角色,它就像一面墙一样,隔离不同的事务。

事务隔离级别脏 读不可重复读幻读
读未提交(read-uncommitted)允许允许允许
不可重复读(read-committed)禁止允许允许
可重复读(repeatable-read)禁止禁止允许
串行化(serializable)禁止禁止禁止

JDBC 提供了这四类事务隔离级别,但默认事务隔离级别对不同数据库而言也是不一样的,我们知道JDBC 只是连接java程序与数据库的桥梁而已,那么数据库又是怎么隔离事务的呢?其实就是运用了锁机制,当插入数据时,就锁定表,这叫“锁表”;当更新数据时,就锁定行,这叫“锁行”。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值