事务详解

189 阅读4分钟

1.什么是事务?

事务是指在逻辑的一组操作,要么全部成功,要么全部失败。要明确的保证数据的准确性。

2.事务的种类

事务分成声明式事务编程式事务,两者分别是什么呢?
编程式事务:我们在业务代码中添加事务控制的代码(如:提交事务、关闭事务),这样的事务控制机制就叫编程式事务。
声明式事务:在使用spring框架进行开发的时候,我们使用XML或者使用@Transactional注解来进行事物控制的方式就叫声明式事务。

3.事务的四大特性(ACID)

我们对事务有了初步的了解,接下来我们说一下事务的四大特性。

原子性( Atomicity ): 原子性是指事务是一个不可分割的工作单位,在一个事务里要保证要么全部都发生操作,要么全部都不发生。原子性是从操作角度来看待事务的,这个操作要么全部成功要么全部失败。

一致性( Consistency ):事务执行前和事务执行后数据必须保持一致。一致性是在数据角度来看待事务。例如:小明有100块钱;小红有100块钱;小明给小红转账50元,那么小明的余额应该是100元减去50最后剩余50元,小红的余额应该是100元加上50元最后变成150元,那么这个事务结束的时候小明加小红的钱必须等于200元。

隔离性( Isolation ):两个事务之间的数据应该是独立的。例如:小明有100元,A事务中小明充值了50元,但是这个事务还没有提交,此时B事务去查询的时候也只能查询到小明原有的100元,不能查询出150元。如果出现其他事务查询出150元这种情况就是读到了A事务尚未提交的数据,也就是脏读

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

3.事务隔离级别

我们刚刚说道了脏读,如果不考虑隔离级别的话就会出现以下几种情况:

脏读:一个线程中的事务读到了另外一个线程中未提交的数据。在说隔离性的时候我们已经说过了,这里就不过多赘述了。

不可重复读:一个线程中的事务读到了另外一个线程中已经提交的update的数据。
举个例子:

  • 员工使用事务A查询工资,查询到自己的工资是1万,此时事务尚未关闭。
  • 财务使用事务B给这位员工涨薪了5千,并且提交了事务。
  • 员工继续使用事物A查询工资,此时查询到的工资成为了1.5万了,原来的1万的工资读不到了,这就叫做不可重复读。

幻读:一个线程中的事务读到了另外一个线程中已经提交的insert或者delete的数据。
举个例子:

  • 财务使用事务A查询工资1万以下有20人,但是事务此时未关闭。
  • 人事使用事务B把其中一员工给裁员了,并且提交了事务。
  • 然后人事继续使用事务A查询工资1万发现只有19人了。然后事务A就很奇怪怀疑是不是自己出现幻觉了,这就是幻读也叫虚读。

其实不可重复度和幻读很像,只是操作数据的形式不同而已。

针对以上可能会出现的问题数据库共定义了四种隔离级别:
串行化(Serializable):可避免脏读、不可重复读、虚读情况的发生。
可重复读(Repeatable Read):可避免脏读、不可重复读情况的发生。(幻读有可能发生)
读已提交(Read Committed):可避免脏读情况发生。不可重复读和幻读一定会发生。
读未提交(Read Uncommitted):最低级别,以上情况均无法保证。(读未提交)

MySQL的默认隔离级别是:读已提交(Read Committed)
可以使用 select @@tx_isolation; 命令来查看。

image.png

4.事务传播行为

事务的传播行为一共有七种:

image.png

最后

希望这篇文章能够帮助到你,文章如果有欠缺或者错误的地方,欢迎各位大佬指正。