事务那点事

一、事务的基本要素(ACID)

  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体

   2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

   3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此互不干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

   4、持久性(Durability):事务完成后,对数据的改变是永久性的,事务对数据库的所有更新将被保存到数据库,不能回滚。

二、事务的并发问题

  ① 脏读:事务A对数据进行了更改,但未提交,事务B可以读取到未提交的数据。如果事务A这时候回滚了,那么事务B就读到了脏数据。

  疑问1:脏读,为啥别人能看到我未提交的数据?
  答:因为其实你对数据库的任何修改都是立即生效的,至于别人看不看的到就是你加了锁没有加锁的事情了。数据库的执行和事务没有关系,事务只是控制这些对数据库所做的操作会不会撤销而已。
       比如A读到了B正在修改的事务是因为B没有加锁,所以别人看到了,MySQL默认是行级锁,所以别人在改数据的时候是加了写锁的,所以别人都读不到这行数据,所以没有脏读问题。 
   
  ② 可重复读:事务A发生了多次读操作,多次操作之间,事务B对数据进行了修改并且提交,这时候读取的数据是不一致的。注:如果中间那个修改的事务没有提交,则读事务看不到修改结果. 在默认的隔离级别下
         

     ③ 幻读:事务A对表进行批量修改,事务B在表里新增数据或者删除,这时候事务A就会丢失对新增数据的修改。发现了自己修改以外的数据,就像是发生了幻觉一样 .
     出现幻读原因 : 因为MySQL的Innodb引擎是默认使用行级锁,没使用表级锁,当我对表中多行数据进行修改的时候,其实也只是锁住了选中的那些行,其他线程插入了新数据是当然可以的 ,也就是事务A根本不知道事务B插入的数据
     如果使用了MySQL 表级锁的的引擎比如MyIsAM,幻读自然就没可能出现了。
       --------------------- 不可重复读侧重于修改,幻读侧重于新增删除

三、MySQL事务的隔离级别 (对应基本要素中的隔离性)

  是:代表会出现脏读,不可重复读,幻读情况

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

 MySQL默认的隔离级别是可重复读(repeatable-read)

    Spring对事务的默认隔离级别是使用的数据库的隔离级别.
    orcale, sqlserver的行级锁只有排他锁没有共享锁,默认不是使用锁机制。而是通过版本控制,不会脏读,但是他会出现重复读问题,因为没锁住这行数据,别人当然可以读。

三、Spring中事务的传播行为 

事务传播行为类型说明
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

 Spring默认使用的是PROPAGATION_REQUIRED

    如果错误,烦请指正,转载请注明出处: https://www.cnblogs.com/icanner/p/9850710.html .谢谢.

   

原文地址:https://www.cnblogs.com/icanner/p/9850710.html