MySQL事务隔离级别

简单来说,事务就是要保证一组数据库操作,要不全部成功,要不全部失败,在 MySQL 中,事务支持是在存储引擎层面的,比如 MySQL 的原生 MyISAM 存储引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因。

一、隔离性

事务的隔离性,就是我们常说的 ICAD(Atomicity,Consistency,Isolation,Durability,即原子性一致性隔离性持久性

  • 原子性:事务的最小单位,保证 MySQL 的一组数据库操作,要不全部成功要不全部失败
  • 一致性:执行事物前后,数据资源保持一致,比如转账,无论转账是否成功,转账者和收款者的总额应该是不变的。
  • 隔离性:并发访问数据库时,不同事物之间的数据应该是隔离的
  • 持久性:一个事物被提交后,他对数据库的数据的改变是持久的,即使数据库发生故障数据也不会变化

当数据库上有多个事务同时执行的时候,就可以出现脏读不可重复读幻读的问题

  • 脏读:A 事务中,读取到 B 事务中修改但未提交的数据,之后 B 事务回滚,导致 A 事务读取到的是一个不存在的数据,即脏数据
  • 不可重复读:A 事务中读取字段 name=lisi,此时 B 事务修改 name=zhangsan 并提交,之后 A 在事务中再次读取 name=zhangsan,这就导致 A 在同一个事务中两次读取到的数据不一致
  • 幻读:幻读跟不可重复读有点像,不过不可重复读针对的同一条记录不可重复读取,幻读指的是 A 事务读取 name=lisi 有四条记录,此时 B 事务删除了一条 name=lisi 的记录,之后 A 再次去读 name=lisi 只能读取到三条记录了,幻读针对的是记录的数量,可以看作是不可重复读的特例

为了解决以上问题,就有了隔离级别的概念

二、隔离级别

再说隔离级别之前,我们应该知道,隔离的越严格,效率就最低,因此我们很多时候,需要在隔离级别和效率之间寻找一个平衡点
SQL 标准的事务隔离级别包括:读未提交(read uncommitted)读已提交(read committed)可重复读(repeatable read)串行化(serializable)

  • 读未提交:一个事务还没提交时,它做的变更就能够被其他事务看到
  • 读已提交:一个事务提交后,它做的变更才能被其他事务看到
  • 可重复读:一个事务执行过程中看到的数据,总跟这个事务在启动时看到的数据是一致的,当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的
  • 串行化;对于同一行记录,写会加写锁,读会加读锁,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行

三、案例

mysql> create table T(c int) engine=InnoDB;
insert into T(c) values(1);

我们来看看在不同的隔离级别下,事务 A 查到的 V1,V2,V3 分别是什么值

  • 读未提交:A 事务能够读取到 B 事务更改未提交的数据,所以 V1=2,V2=2,V3=2
  • 读已提交:A 事务只能读取到 B 事务提交后的数据,所以 V1=1,V2=2,V3=2
  • 可重复读:在 A 事务开启后,读取到的数据都是一样的,所以 A 事务开始的时候值是 1,所以 V1=1,V2=1,V3=2
  • 串行化:在事务 B 将 1 改成 2 的时候,会被锁住,直到 A 事务提交后,事务 B 才能继续执行,所以从 A 的角度来看,V1=1,V2=1,V3=2

在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准

  • 可重复读隔离级别下,这个事务是事务启动时创建的,整个事务存在期间都用整个视图
  • 读已提交隔离级别下,整个视图是在 SQL 语句开始执行的时候创建的
  • 这里值得注意的是,读未提交隔离级别下直接返回记录上的最新值,没有视图概念
  • 串行化隔离级别则是通过直接加锁的方式来避免并行访问

四、总结

在不同的隔离级别下,数据库行为是不同的,Oracle数据库默认隔离级别是读已提交MySQL默认隔离级别是可重复读,如果存在 Oracle 迁移到 MySQL,为保证数据库隔离级别一致,需要将 MySQL 的隔离级别改成读已提交

MySQL 配置的方式是,将启动参数transaction-isolation的值设置成READ-COMMITTED,可以使用show variables like 'transaction_isolation';来查看当前隔离级别

正常情况下,为了保证效率,我们一般都会把事务隔离级别调整成读已提交,那么什么时候需要可重复读的场景呢?大多数在做数据校对的时候,不希望有其他事务来干扰数据,启动可重复读是很方便的


我是一零贰肆,一个关注Java技术和记录生活的博主。

欢迎扫码关注“一零贰肆”的公众号,一起学习,共同进步,多看路,少踩坑。

posted @ 2024-04-02 13:18  孙半仙人  阅读(41)  评论(0编辑  收藏  举报