说起事务,什么是事务?指访问并可能更新数据库中各种数据项的一个程序执行单元。主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务。
严格意义上的事务实现应该是具备原子性、一致性、隔离性和持久性,简称 ACID。数据库事务有四个隔离级别,读未提交、读已提交、可重复读、可串行化,不同的数据库默认的隔离级别也是不一样的,大多数数据库的默认隔离级别为: 读已提交,如Sql Server , Oracle等,少数数据库默认的隔离级别为可重复读, 如MySQL InnoDB存储引擎。不同的隔离级别还会存在不同的问题,如图:
脏读:一个事务里面,读取到了其他事务没有提交事务的数据
我们可以看到,左边第1步设置了下读未提交级别,第2步开启了一个事务,然后第3步我们查询了一下数据,接着去右边执行第4,5步开启一个事务并修改了id=1的数据,然后去左边第6步重新查就可以查到右边事务里没提交的更新后的数据。这就是读未提交级别产生的脏读现象。
不可重复读:同一个事务里面,可以读取到其他事物提交后的数据,导致两次同样的查询,数据返回不一致。
我们可看到第4步设置了读已提交级别,第5步开启了一个事务,第6步查询了一下,然后在右边执行第7步,开启了一个事务,第8步去更新id=2的数据,赶紧的我们去看下左边事务里数据是否改变,很明显,第9步重新查,发现数据并没有变化,也就是说读已提交级别解决了脏读的问题。接着我们第10步把右边的事务提交了,再去左边的事务里第11步可以看到,已经和第9步返回的数据不一样了,这就是在同一个事务里读已提交级别的不可重复读现象。
幻读:同一个事务里读取不到其他事务操作提交后的数据,事务提交后才能看到别的事务更新后的数据。
左边第1步前面我们设置了隔离级别为可重复读,并开启了一个事务,然后查询了一下,然后我们去右边执行第2,3,4步,重新开启一个事务然后更新了id=1的数据然后提交了,接着我们去左边执行第5步可以看到,数据还是我们第一步查出来的数据没变化,解决了不可重复读的问题。但是我们第6步提交事务后,执行第7步重新查询,就可以看到了刚才左边事务提交的数据,就跟幻觉一样,这就是,可重复读级别的幻读现象。
除了上面我们提到的三种隔离级别,还有一种叫串行,见名知义,一个挨着一个,像一个串一样,依次执行,可以解决上面所有的问题,缺点是效率低。
我们第1步设置了隔离级别为串行,然后第2步开启了一个事务,然后第3步进行查询,接着我们去右边第4步开启了一个事务,执行第5步插入语句,发现卡住了,接着下面我们把第二张图的左边的事务提交了,然后右边刚才的插入语句就可以执行了。
说完了事务的隔离界别,就不得不提Spring里的事务的传播行为,有7种,默认的那种叫REQUIRED,意思是当前有事务就加入当前事务运行,当前没事务,就创建一个事务运行。话不多少,咱们7种都看看都有哪些传播行为吧:
看完了都有这么几种,我们具体怎么使用呢,两种方式,xml配置和注解方式。先来看看xml的怎么配置的,一些涉及到数据变化增删改查之类的方法名开头的都设置了REQUIRED级别,其他查询类的不涉及到数据修改的不需要事务的方法都设置的SUPPORTS级别。
当然了我们也可以用注解的方式来使用,spring的xml里如下图配置或者下面springboot直接在启动类上加上@EnableTransactionManagement。
然后我们在需要开启事务的方法上用类似这样的方式来指定事务的传播行为。@Transactional(propagation=Propagation.REQUIRED)
提到事务就不得不提分布式事务了,这个小编就不过多展开了,推荐给大家一篇小编转载的文章,6种解决分布式事务的方案《分布式事务》给大家学习下,就不在赘述了。最后,大家想获取更多知识的,可以继续关注公众号,不定时推送。分享了这么牛逼的知识,还不请小编喝个水吗,哈哈哈,欢迎土豪直接赏赞,谢谢,您的支持就是小编最大的动力。