事务常规理解

一:事务四大特性

  • 原子性(Atomicity);事务必须是一个不可分割的整体,就像我们在化学课里学到的原子,原子是构成物质的最小单位。于是,人们就归纳出事务的第一个特性,
  • 一致性(Consistency):也就是说,执行完数据库操作后,数据不会被破坏。打个比方,如果从 A 账户转账到 B 账户,不可能因为 A
    账户扣了钱,而 B 账户没有加钱吧。
  • 隔离性:当我们编写了一条 update 语句,提交到数据库的一刹那间,有可能别人也提交了一条 delete
    语句到数据库中。也许我们都是对同一条记录进行操作,可以想象,如果不稍加控制,就会出大麻烦来。我们必须保证数据库操作之间是“隔离”的
  • 持久性(Durability):数据永久地存放在磁盘中,这个也算事务的一条特性

注:这 4 条特性,是事务管理的基石,一定要透彻理解。此外还要明确,这四个家伙当中,谁才是老大?

其实想想也就清楚了:原子性是基础,隔离性是手段,持久性是目的,真正的老大就是一致性。数据不一致了,就相当于“江湖乱套了”。所以说,这三个小弟都是跟着“一致性”这个老大混,为他全心全意服务。

这四个家伙当中,其实最难理解的反倒不是一致性,而是隔离性。因为它是保证一致性的重要手段,是工具,使用它不能有半点差池,否则后果自负!

二:常规数据问题

三类数据读问题

  1.Dirty Read(脏读)

  2.Unrepeatable Read(不可重复读)

  3.Phantom Read(幻读)
两类数据更新问题

  1.第一类丢失更新

  2.第二类丢失更新

5种问题可以自行百度;
简单点就是:
1.脏读:事务 A 读取了事务 B 未提交的数据,并在这个基础上又做了其他操作。
两个事务都做了修改操作,做完后都做了一次查询,事务没有隔离开,被互相影响到了;
2.不可重复读:事务 A 读取了事务 B 已提交的更改数据。
3.幻读:事务 A 读取了事务 B 已提交的新增数据。

第一条是坚决抵制的,后两条在大多数情况下可不作考虑。
第一类更新可以理解为:
事务A,事务b都做了写操作,A因为回滚覆盖了B
第二类更新可以理解为:
事务B后提交的,吧事务A覆盖了;
理论上,第一种更新问题不允许出现,,第二类,一般数据库靠锁来等待,或者你的sql是个覆盖的sql

三:数据库事务和锁

数据库四个隔离级别:

事务隔离级别(Transaction Isolation Level)
1.READ_UNCOMMITTED

  2.READ_COMMITTED

  3.REPEATABLE_READ

  4.SERIALIZABLE
从上往下,级别越来越高,并发性越来越差,安全性越来越高,反之则反。

在这里插入图片描述
数据库锁也是保证数据库数据不发生紊乱的法则之一:

例如,orcal:
读操作不影响:一般查询共享锁;加入for update 会锁响应数据,不希望别人来更新;
修改某条数据,一般会加行锁,看是否用到索引,行锁与表锁的切换;
新增某条记录,一般加表锁
可参考:orcal数据库的锁

四:java程序中的事务、以及锁

第三步保证的数据库中事务的处理,以及不影响数据,
但是程序中,如何在数据库正常的情况下,自己程序导致的数据紊乱呢;

Spring 一下子就提供了 7 种事务传播行为,

  1.PROPAGATION_REQUIRED

  2.RROPAGATION_REQUIRES_NEW

  3.PROPAGATION_NESTED

  4.PROPAGATION_SUPPORTS

  5.PROPAGATION_NOT_SUPPORTED

  6.PROPAGATION_NEVER

  7.PROPAGATION_MANDATORY

4.1事务的传播行为:
也可以理解为,一次请求,会访问多个方法,多个方法直接的事务是怎么影响的;
例如:
从方法 A访问方法 B。Spring 解决的只是方法之间的事务传播:
假如方法B出现了问题,如果方法a有写操作,会有什么影响呢?
报错还是一起回滚呢?一起回滚的花,主事务是A还是B呢?

假设事务从方法 A 传播到方法 B,您需要面对方法 B,问自己一个问题:
方法 A 有事务吗?

如果没有,就开启一个事务;如果有,就加入当前事务(方法A加入到方法B)。这就是 PROPAGATION_REQUIRED,它也是 Spring 提供的默认事务传播行为,适合绝大多数情况。
如果没有,就开启一个事务;如果有,就将当前事务挂起。这就是 RROPAGATION_REQUIRES_NEW,意思就是创建了一个新事务,它和原来的事务没有任何关系了。
如果没有,就开启一个事务;如果有,就在当前事务中嵌套其他事务。这就是 PROPAGATION_NESTED,也就是传说中的“嵌套事务”了,所嵌套的子事务与主事务之间是有关联的(当主事务提交或回滚,子事务也会提交或回滚)。
如果没有,就以非事务方式执行;如果有,就使用当前事务。这就是 PROPAGATION_SUPPORTS,这种方式非常随意,没有就没有,有就有,有点无所谓的态度,反正我是支持你的。
如果没有,就以非事务方式执行;如果有,就将当前事务挂起。这就是 PROPAGATION_NOT_SUPPORTED,这种方式非常强硬,没有就没有,有我也不支持你,把你挂起来,不鸟你。
如果没有,就以非事务方式执行;如果有,就抛出异常。这就是 PROPAGATION_NEVER,这种方式更猛,没有就没有,有了反而报错,确实够牛的,它说:我从不支持事务!
如果没有,就抛出异常;如果有,就使用当前事务。这就是 PROPAGATION_MANDATORY,这种方式可以说是牛逼中的牛逼了,没有事务直接就报错,确实够狠的,它说:我必须要有事务!

默认事务传播行为: PROPAGATION_REQUIRED ,有就加入;

Spring 给我们带来了事务传播行为,这确实是一个非常强大而又实用的功能。除此以外,也提供了一些小的附加功能,比如:

1.事务超时(Transaction Timeout):为了解决事务时间太长,消耗太多的资源,所以故意给事务设置一个最大时常,如果超过了,就回滚事务。

2.只事务(Readonly Transaction):为了忽略那些不需要事务的方法,比如读取数据,这样可以有效地提高一些性能。

注解事务比较方便:只需:

@Transactional  
public void xxx() {  
    ...  
}

4.2 多线程情况下的数据问题
4.1可以理解为单线程,或者多线程情况下,一次请求,各种操作事务如何嵌套的,如果出现问题,事务回滚

多线程情况下,一般都是私有变量,或者常量,或者每次查询操作,最后一步统一实现写入数据库操作,事务最后一次commit提交;

还有一种情况就是,多个线程共用一个公共数据了,并且需要修改,,这这时候,就需要用到程序上的,同步、锁、等api操作了,保证数据不能出现问题
:额外在补充4.2锁

参考文献:https://blog.csdn.net/u014079773/article/details/52808193?spm=1001.2014.3001.5506
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值