事务管理详细说明及Spring事务管理

什么是事务

事务是由N步数据库操作序列组成的逻辑执行单元,这系列操作要么全执行,要么全放弃执行。

事务的特性(ACID)

  • 原子性(Atomicity):事务是应用中不可再分的最小执行体
  • 一致性(Consistency):事务执行的结果,须使数据从一个一致性状态,变为另一个一致性状态
  • 隔离性(Isolation):各个事务的执行互不干扰,任何事务的内部操作对其他的事务都是隔离的
  • 持久性(Durability):事务一旦提交,对数据所做的任何改变都要记录到永久存储器中。

事务的隔离性

常见的并发异常

  • 第一类丢失更新

某一事务的回滚,导致另外一个事务已更新的数据丢失了

  • 第二类丢失更新

某一个事务的提交,导致另外一个事务已更新的数据丢失了

  • 脏读

某一个事务,读取了另一个事务未提交的数据

  • 不可重复读

某一个事务,对同一个数据前后读取的结果不一致

  • 幻读

某一个事务,对同一个表前后查询到到的行数不一致

常见的隔离级别

  • Read Ubcommitted :读取提交的数据
  • Read Committed :读取已提交的数据
  • Repeatable Read :可重复读
  • Serializable:串行化

 

一般情况下,要求性能更高的时候选择Read Committed,要求安全性更高的时候选择Repeatable Read

实现机制

  • 悲观锁(数据库)
  1. 共享锁(S锁)

    事务A对某数据加了共享锁之后,其他事务只能对该数据加共享锁,但不能加排他锁(其他事务只能读,不能改)

     2.排他锁(X锁)

事务A对某数据加了排他锁之后,其他事务对该数据既不能加共享锁,也不能加排他锁(其他事务不能读,也不能改)

  •  乐观锁(自定义)

通过加版本号或者时间戳等字段

在更新数据前,检查版本号是否发生变化。若变化则取消本次更新,否则就更新数据(版本号+1)

Spring事务管理(两种方式)

  • 声明式事务(两种方式)

  1. 通过XML配置,声明某方法的事务特征
  2. 通过注解,声明某方法的事务特征
// REQUIRED: 支持当前事务(外部事务),如果不存在则创建新事务.
    // REQUIRES_NEW: 创建一个新事务,并且暂停当前事务(外部事务).
    // NESTED: 如果当前存在事务(外部事务),则嵌套在该事务中执行(独立的提交和回滚),否则就会REQUIRED一样.
//propagation 事务传播机制,以上是三个值
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public Object save1() {
        // 新增用户
        User user = new User();
        user.setUsername("alpha");
        user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
        user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
        user.setEmail("alpha@qq.com");
        user.setHeaderUrl("http://image.nowcoder.com/head/99t.png");
        user.setCreateTime(new Date());
        userMapper.insertUser(user);

        // 新增帖子
        DiscussPost post = new DiscussPost();
        post.setUserId(user.getId());
        post.setTitle("Hello");
        post.setContent("新人报道!");
        post.setCreateTime(new Date());
        discussPostMapper.insertDiscussPost(post);

        Integer.valueOf("abc");//这里将会报错,当报错时,事务会回滚,不会向数据库中存储数据,这就是优点

        return "ok";
    }
  • 编程式事务(局部控制)

        通过Transaction Template这个类管理事务,并通过它执行数据库的操作


    @Autowired
    private TransactionTemplate transactionTemplate;
public Object save2() {
        transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        return transactionTemplate.execute(new TransactionCallback<Object>() {//匿名实现这个接口
            @Override
            public Object doInTransaction(TransactionStatus status) {
                // 新增用户
                User user = new User();
                user.setUsername("beta");
                user.setSalt(CommunityUtil.generateUUID().substring(0, 5));
                user.setPassword(CommunityUtil.md5("123" + user.getSalt()));
                user.setEmail("beta@qq.com");
                user.setHeaderUrl("http://image.nowcoder.com/head/999t.png");
                user.setCreateTime(new Date());
                userMapper.insertUser(user);

                // 新增帖子
                DiscussPost post = new DiscussPost();
                post.setUserId(user.getId());
                post.setTitle("你好");
                post.setContent("我是新人!");
                post.setCreateTime(new Date());
                discussPostMapper.insertDiscussPost(post);

                Integer.valueOf("abc");

                return "ok";
            }
        });
    }

一般情况下选择声明式事务,但如何业务复杂,只想管理中间某块事务,可以选择第二种编程式事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大磊程序员(“hello world”)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值