mysql四种事务隔离级别

转载自:https://www.cnblogs.com/xrq730/p/5087378.html

什么是事务?

  • 事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换为另一种状态。
  • 事务必须ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)、隔离性(isolation)、一致性(consistency)、持久性(durability)的缩写。

ACID:

  • 原子性:即不可分割,事务要么被全部执行,要么全部不执行。如果事务的所有子事务全部提交成功,则所有的数据库操作被提交,数据库状态发生变化;如果有子事务失败,则其他子事务的数据库操作被回滚,即数据库回到事务执行前的状态,不会发生状态转换。
  • 一致性:事务的执行使得数据库从一种正确状态转换成另一种正确状态。
  • 隔离性:在事务正确提交前,不允许把事务对该数据的改变提供给其他任何事务,即在事务正确提交前,它可能的结果不应该显示给其他事务。
  • 持久性:事务正确提交之后,其结果将永远保存在数据库中,即使事务提交之后有了其他故障,事务的处理结果也会得到保存。

事务的作用:

  • 事务管理对于企业级应用而言至关重要,它保证了用户的每一次操作都是可靠的,即使出现了异常的访问情况,也不至于破坏后台数据的完整性。就像银行的自动提款机ATM,通常ATM都可以正常为客户服务,但是也难免遇到操作过程中突然出现的故障情况,此时,事务就必须确保出故障前对账户的操作不生效,就像用户刚才完全没有使用过ATM机一样,以保证用户和银行的利益都不受损失。

并发下事务会产生的问题:

  1. 脏读:所谓脏读就是,事务A读取到了事务B还没提交的数据。比如银行取钱,事务A开启,此时切换到了事务B,事务B开始事务,取走100,此时切换回事务A读取的数据肯定是数据库中的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额还是原始余额,这就是脏读
  2. 不可重复读:所谓不可重复读,就是在一个事务中两次读取了某个数据,读出来的数据不一样。银行取钱为例,事务A开启事务,查出银行卡剩余1000,此时切换到事务B,事务B取走100并提交,余额变成900了,此时切换回事务A,事务A再查一次查出账户余额为900元,这对事务A而言,在同一个事务内两次读取的账户余额数据不一致,这就是不可重复度。
  3. 幻读:所谓幻读,就是指在一个事务里面的操作中发现了未被操作的数据。比如学生信息,事务A开启事务,修改所有学生签到的状况为false,此时切换到了事务B,事务B开启,事务B插入了一条学生的数据,此时切换回事务A,事务A提交的时候发现了一条自己没有修改过的数据,这就是幻读。幻读出现的前提是并发的事务中有事务发生了插入、删除的操作。

事务的隔离级别:

事务的隔离级别就是为了解决上面几种问题诞生的。为什么要有隔离级别,因为隔离级别越高,在并发下会产生的问题越少,但同时付出的性能消耗也越大,因此很多时候必须在并发性和性能之间做一个权衡。所以设置了几种食物隔离级别,以便让不同的项目可以根据自己的项目的并发情况选择合适的事务隔离级别,对于在事务隔离级别之外会产生的并发问题,在代码中做补偿。

事务隔离级别有4中,但是像spring会提供给用户5种,来看下:

  1. DEFAULT:默认隔离级别,每种数据库支持的事务隔离级别不一样,如果spring配置事务时将isolation设置为这个值话,那么将使用底层数据库的默认事务隔离级别。顺便说一句,如果使用的是mysql,可以使用“SELECT @@tx_isolation” 来查看默认的事务隔离级别
  2. READ_UNCOMMITTED:读未提交,即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种。
  3. READ_COMMITTED:读已提交,即能够读取到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读;
  4. REPEATABLE_READ:重复读取,即在数据读出来后加锁,类似“select * from  A for update”,明确读取的数据就是为了更新使用,所以要加一把锁,防止别人修改它。Repeatable_read的意思也类似,读取一条数据,这个事务不结束,别的事务不可以改这条记录,这样解决了脏读、不可重复读的问题,但是幻读的问题无法解决
  5. SERLALIZABLE:串行化,最高事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务才可以执行另一个事务里面的所有子事务,这样就解决了脏读、不可重复度、幻读的问题

事务隔离界别解决的并发问题:

mysql四种事务隔离级别_第1张图片

强调不是事务的隔离级别越高越好,事务的隔离级别设置的越高,势必要花手段去加锁用以保证事务的正确性,那么效率就要降低,因此实际开发中往往要在效率和并发正确性之间做一个取舍,一般情况下会设置为READ_COMMITED,此时避免了脏读,并发性也不错,之后通过一些手段去解决不可重复度和幻读的问题就好了。

 

事务隔离级别的查看和修改

首先说明下MySql查看和修改事务隔离级别的几个命令:

  • 查看事务隔离级别使用 select @@tx_isolation
  • 修改当前会话事务隔离级别使用 set session TRANSACTION ISOLATION LEVEL Serializable;(参数可以为:Read uncommitted|Read committed|Repeatable read|Serilizable)
  • 修改全局事务隔离级别使用SET global TRANSACTION ISOLATION LEVEL Serializable;(参数可以为:Read uncommitted|Read committed|Repeatable read|Serializable)

修改了会话的事务隔离级别,比如MyBatis,getSqlSession()的时候,只针对这一次拿到的session有效;比如CMD命令行,只对这一次窗口有效。

修改了全局事务隔离级别,那么针对此后所有的会话有效,当前已经存在的会话不受影响。

 

关于MySql的事务隔离级别,推荐大家一篇文章,很详细的测试了四种事务隔离级别https://www.cnblogs.com/snsdzjlz320/p/5761387.html

你可能感兴趣的:(mysql)