事务的四大特性和隔离级别

什么是事务

百度百科中解释:指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
简单的说,事务就是并发控制的单位,是用户定义的一个操作序列。 而一个逻辑工作单元要成为事务,就必须满足ACID属性。
A:原子性(Atomicity)
事务中的操作要么都不做,要么就全做。 C:一致性(Consistency)
事务执行的结果必须是从数据库从一个一致性状态转换到另一个一致性状态。 I:隔离性(Isolation)
一个事务的执行不能被其他事务干扰 D:持久性(Durability)
一个事务一旦提交,它对数据库中数据的改变就应该是永久性的

事务又分为本地事务和分布式事务:

什么是本地事务(Local Transaction)?

本地事务也称为数据库事务或传统事务(相对于分布式事务而言)。它的执行模式就是常见的:

transaction begin
insert/delete/update
insert/delete/update

transaction commit/rollback
本地事务有这么几个特征:

一次事务只连接一个支持事务的数据库(一般来说都是关系型数据库)
事务的执行结果保证ACID
会用到数据库锁

什么是分布式事务

分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
数据库分库分表
当数据库单表一年产生的数据超过1000W,那么就要考虑分库分表,具体分库分表的原理在此不做解释,以后有空详细说,简单的说就是原来的一个数据库变成了多个数据库。这时候,如果一个操作既访问01库,又访问02库,而且要保证数据的一致性,那么就要用到分布式事务。
事务的四大特性和隔离级别

事务的四大特性

  1. 原子性(Atomicity)
      原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
  2. 一致性(Consistency)
      一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
      拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
  3. 隔离性(Isolation)
      隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
      即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
      关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。
  4. 持久性(Durability)
      持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
    例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

隔离级别

  • 脏读   脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
      当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如:用户A向用户B转账100元
  • 不可重复读
      不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
      例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。
      不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
  • 虚读(幻读)
      幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
  • 1.未提交读(READ UNCOMMITTED):事务中的修改,即使没有提交,对其它事务也是可见的。最低级别,任何情况都无法保证。
  • 2.提交读(READ COMMITTED):一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。可避免脏读的发生。
  • 3.可重复读(REPEATABLE READ):保证在同一个事务中多次读取同样数据的结果是一样的。可避免脏读、不可重复读的发生。
  • 4.可串行化(SERIALIXABLE):强制事务串行执行。可避免脏读、不可重复读、幻读的发生。
  • 以上四种隔离级别最高的是SERIALIXABLE(可串行化)级别,最低的是READUNCOMMITTED(未提交读)级别,当然级别越高,执行效率就越低。
    像SERIALIXABLE(可串行化)这样的级别,就是以锁表的方式使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。
    在MySQL数据库中,支持上面四种隔离级别,默认的为REPEATABLEREAD(可重复读);
    而在Oracle数据库中,只支持SERIALIXABLE(串行化)级别和READCOMMITTED(读已提交)这两种级别,其中默认的为READ
    COMMITTED级别。
    这张图就是四大隔离级别分别解决了哪些问题:事务的四大特性和隔离级别