MySQL - 事务隔离级别

并发事务问题

脏读

概念: 一个事务读到另外一个事务还没提交的数据

举例:
事务A:第一步:select 第二步:update 第三步:…
事务B:第一步:select 第二步:…

假设原本在数据库中的 数据C = 1,那么

  1. 事务A进行到第二步修改了数据库中的 数据C =2
  2. 此时事务B开始第一步,读取事务A修改后的 数据C=2
  3. 但是此时事务A未将事务提交,有可能会进行事务的回滚,数据C 被修改回原来的值 =1
  4. 而事务B此时持有的就是错误的 数据C =2

不可重复复

概念: 一个事务先后读取同一条记录,但两次读取到的数据不同

举例:
事务A:第一步:select 第二步:… 第三步:select
事务B:第一步:… 第二步:update 第三步:提交事务

  1. 事务A执行到第一步,查询 数据C =1
  2. 接着事务B 执行到第二步,修改了数据C =2
  3. 接着事务B 执行到第三步,提交了事务
  4. 接着事务A执行到第三步,再次查询数据C =2
  5. 但此时事务A发现,前后两次查询数据C的值不一样,这就出现了 不可重复读

幻读

概念: 一个事务按照查询条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在

举例:
事务A:第一步:select 第二步:insert 第三步:select
事务B:第一步:… 第二步:insert 第三步:提交事务

  1. 事务A要插入一条 id=1 的数据,第一步先查询数据库中是否有 id=1 的数据,发现没数据
  2. 接下来事务B 刚好执行到第二步,插入了一条 id=1 的数据
  3. 事务B执行到第三步,提交了事务
  4. 而事务A此时进行到第二步,要往数据库中插入 id=1 的数据,结果发现已经存在了
  5. 但是事务A接着执行第三步查询,结果查询到的结果还是没有

事务隔离级别设置方法

查看事务隔离级别

SELECT @@TRANSACTION_ISOLATION;

设置事务隔离级别

SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

其中的 [ SESSION | GLOBAL ] 选择是只对当前会话进行设置还是对全局进行设置

事务隔离级别详解

读未提交(Read uncommitted)

效果 – 相当于没有隔离,三种并发事务问题都会发生

虽然 读未提交的隔离级别 的数据安全性最差,但是性能最高,因为其并发程度最高

读已提交(Read committed)

Oracle的默认隔离级别

效果 – 解决了脏读问题

例如上面的脏读例子:
事务A:第一步:select 第二步:update 第三步:提交
事务B:第一步:select 第二步:… 第三步:select

假设原本在数据库中的 数据C = 1,那么

  1. 事务A进行到第二步修改了数据库中的 数据C = 2
  2. 此时事务B开始第一步,读取的不再是事务A修改后的 数据C ,而是原本的值 数据C=1
  3. 等事务A将事务提交
  4. 事务B再次读取 数据C,才会读取到事务A修改的 数据C=2

这就解决了脏读问题

可重复读

MySQL的默认隔离级别

效果 – 解决了 脏读、不可重复读 问题

例如上面的不可重复读例子:
事务A:第一步:select 第二步:… 第三步:select
事务B:第一步:… 第二步:update 第三步:提交事务

  1. 事务A执行到第一步,查询 数据C =1
  2. 接着事务B 执行到第二步,修改了数据C =2
  3. 接着事务B 执行到第三步,提交了事务
  4. 接着事务A执行到第三步,再次查询到的不是事务B已经提交的数据C=2,还是之前的C=1

这就解决了不可重复读的问题

串行化

效果 – 解决了 脏读、不可重复读、幻读 问题

串行化就是同步,不存在并发,那肯定就没有并发事务问题

但是没有并发,也就意味着,串行化对性能的影响很大

举例:
事务A:第一步:select 第二步:insert 第三步:select
事务B:第一步:insert 第二步:… 第三步:提交事务

  1. 事务A要插入一条 id=1 的数据,第一步先查询数据库中是否有 id=1 的数据,发现没数据
  2. 接下来事务B 刚要开始执行第一步插入id=1的数据,但是此时因为事务A在进行,事务B不能并发,会被阻塞
  3. 必须等事务A进行到第二步,要往数据库中插入 id=1 的数据,接着执行后面的步骤直到提交事务
  4. 事务A提交后,事务B才会开始进行第一步,但是这个时候事务B就会发现id=1的数据已经存在,插入失败

这就解决了幻读的问题

总结

事务隔离级别越高,数据越安全,但是性能越低

你可能感兴趣的:(MySQL,mysql,数据库,oracle)