我们再来认识一下事务

我尽量用最白话的词来阐述我所认识的事务,有误欢迎指导交流。

四个特性

  • 原子性:要么都变,要么都不变。
  • 一致性:变后和预期一致。
  • 隔离性:事务之间影响范围。
  • 持久性:操作后数据落库持久化。

隔离级别

上面说到四个特性有一个隔离性,但这个隔离性并不是固定的,而是可配置(当然每个数据库有默认值,比如mysql默认是可重复读,Oracle是读提交)。

了解隔离级别前,先熟悉三个概念:脏读、重复读、幻读。

脏读:读到另外一个事务还没有提交的数据。
    一个事务修改了用户数据,但是还没有提交事务,另外事务查询用户数据能读到此类数据。

重复读:读到了已经提交的事务的数据,针对数据的变更。
    一个事务修改了用户数据,并且提交事务,另外一个事务能查询到所提交的数据。
    
幻读:读到了已经提交的事务的数据,针对数据的新增。
    一个事务新增了用户数据,并且提交事务,另外一个事务能查询到所提交数据,出现两次查询不一致的情况。

隔离级别的几种

  • 不支持事务
  • 读未提交【read_uncommited】
  • 读提交【read_committed】
  • 可重复读【repeatable_read】
  • 序列化【serializable】

下面用表格来呈现隔离级别和脏读幻读重复读出现的情况。

隔离级别脏读重复读幻读
不支持事务
读未提交
读提交-
可重复读--
序列化---

打钩表示会出现。

怎么用事务

jdbc

默认会开启事务,在单条执行后提交事务。
当然可以关闭自动提交。使用commit()和rollback()来控制事务提交和回滚。
Connection conn = DriverManager.getConnection("url","name","passwd");
try {
    //关闭自动提交事务
    conn.setAutoCommit(false);        
    stme = conn.createStatement();    
    stmt.excuteUpdate("执行sql语句");  
    conn.commit(); 
} catch(Exception e) {
    e.printStackTrace();
    conn.rollback();                
} fianlly {
    if(stmt != null)                  
        stmt.close();                 
    if(conn != null)                 
        conn.close();                 
}    

jta

此处不阐述使用例子。

jdbc就是针对单体服务、单个数据库的事务控制,那么碰到多个服务多个数据库jdbc就处理不了。这时候就需要jta,其提供的api能控制多个服务间的事务开始、回滚、提交等。

spring

上面两个说是编程式事务,那么spring出现带来了声明式事务。

同时也带来事务传播机制。

声明式事务:

spring声明式事务是在AOP基础上进行,在目标方法前创建事务,执行之后收回并根据异常确定是否回滚。

spring声明式事务,可以基于多种形式,现在主要使用的是基于@Transactional的声明式事务,也就是基于注解。

spring事务传播机制:

有7中传播行为
propagetion_required  支持当前事务,如无事务,新建一个
propagetion_supports  支持当前事务,如无事务,不使用
propagetion_mandatory 支持当前事务,如无事务,抛出异常
propagetion_requires_new  如有事务存在,挂起当前事务,新建一个事务(无论当前有无,都会新建一个事务)
propagetion_not_supported  支持非事务方式运行,如有事务,挂起
propagetion_never  以非事务方式运行,有事务则抛出异常
propagetion_nested 嵌套事务(结合保存点使用,当内嵌回滚,外部事务不受影响)

简单记忆:需要事务、支持或不支持事务、需要或不需要事务、新事务或内嵌事务。(需要不需要会报错,支持不支持会挂起,新事务分开提交不影响外层,内嵌事务同时提交)

spring事务不生效的几种原因:

  • 检查事务是否开启
  • 检查@Transactional注解是否是接口,是否public修饰
  • 检查数据库引擎(mysql的myisam就是不支持事务的)
  • spring是否扫描到你的包
  • 异常是否是检查异常
  • 是否是同一个类中调用(比如A类中的a()调用b()方法,这样事务是不会生效的,spring动态代理的逻辑了解下)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值