InnoDB事务隔离级别

  • 脏读
    事务1 可以访问 事务2 中未提交的数据
会话1会话2
beginbegin
update table set age = 10 where id = 1
select age from table where id = 1
commitcommit / rollback

会话2将age的值改变,且并未提交,此时会话1select查询结果为10.
如果会话2 最终的结果是commit,那么此查询没有问题
但是如果会话2 最终选择rollback回滚,那么会话1 的查询结果是不正确的。

  • 不可重复读
    事务1 中包括了多次查询,但是结果却不一样
会话1会话2
beginbegin
select age from table where id = 1
update table set age = 10 where id = 1
commit
select age from table where id = 1
commit

会话1 两次查询结果不一致,原因是会话2 进行了事务的提交。
需要注意的是两次查询是在同一个事务中的。

  • 幻读
    事务1 中包括了多次查询,但是结果数量却不一样(数据增多或减少)
会话1会话2
beginbegin
select age from table where id > 2
insert into table(id,age) values (5,10)
commit
select age from table where id > 2begin
commit

会话2 进行了数据的插入或删除操作,并且提交。

MYSQL中(InnoDB引擎)的四种事务隔离级别

隔离级别脏读不可重复读幻读
Read Uncommitted (读未提交)VVV
Read Committed(读已提交)XVV
Repeatable Read(可重复读)(默认级别)XXV
Serializable(串行化)XXX

InnoDB引擎针保证数据一致性的原理:

1.MVCC
在每一行数据中加上两个隐藏字段,记录行的创建时间过期时间,但实际存储的是版本号,而不是时间,每开启一个新的事物,版本号加一。

  • select:读取创建版本小于等于当前版本的记录,保证在读取之前记录是存在的。
    (上述不可重复读的例子,会话2首先进行commit操作,那么被更新过的 age=10这条记录的版本号将会大于 会话1 中的版本号,会话1 将不会查询这条记录)
  • insert:将当前事务的版本号保存至数据行的创建版本号
  • update:新插入一行,以当前事务的版本号作为新行的创建版本号,同时将原记录行的过期版本号设置为当前事务版本号。
  • delete:将当前事务的版本号保存至行的删除版本号

2.InnoDB实现MVCC的方式:Consistent Read
首先看两个概念
快照读:读取的是快照版本,也就是历史版本
当前读:读取的是最新版本
普通的SELECT就是快照读,而UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE是当前读。
一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(MVVC)读取当前数据库中行数据的方式。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。相反地,InnoDB会去读取行的一个快照。
在这里插入图片描述
一致性非锁定读是InnoDB默认的读取方式,即读取不会占用和等待行上的锁

事务隔离级别READ COMMITTED和REPEATABLE READ,InnoDB使用一致性非锁定读

然而对于快照数据的定义却不同:
READ COMMITTED事务隔离级别下,一致性非锁定读总是读取被锁定行的最新一份快照数据。
而在REPEATABLE READ事务隔离级别下,则读取事务开始时的行数据版本。
在这里插入图片描述

如果只是有MVCC,并不能保证增删改查一致性:
假设事务A更新表中id=1的记录,
而事务B也更新这条记录,并且B先提交,
如果按照前面MVVC说的,事务A读取id=1的快照版本,那么它看不到B所提交的修改,
此时如果直接更新的话就会覆盖B之前的修改,B的修改就丢失了,这是不允许的。

所以,在修改的时候一定不是快照读,而是当前读。

3.间隙锁
防止其他事务在锁定的区域内插入数据,防止了幻读。

总结
本来只有 Serializable 隔离级别才可以解决幻读问题,
而实际上由于 InnoDB 快照读 的特性使 Repeatable Read 也解决了幻读问题。
当前读 中的幻读问题,innodb默认为它加入了间隙锁,从而避免出现幻读。

使用场景:

  1. 快照读(snapshot read)
    简单的select操作(不包括 select … lock in share mode, select … for update)

  2. 当前读(current read)
    select … lock in share mode
    select … for update
    insert
    update
    delete

在Repeatable Read(可重复读)(默认级别)下:
快照读 是通过MVVC(多版本控制)实现;
当前读 是通过加record lock(记录锁)和gap lock(间隙锁)来实现的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值