08 | 事务到底是隔离的还是不隔离的?MVCC

思考:

首先,事务在可重复读的隔离级别下,同一事务读的值不会改变,那么在发生行锁竞争等待中,别的事务进行了数据修改,结果如何?

此处Q1读到的值是3,而Q2读到的值是1

原因:主要是因为mvcc(多版本并发控制)

mvcc基本概念:

undo log:记录数据库的操作

版本链:存储的记录中除了本身数据,还有两个字段trx_id(事务id,自增),roll_pointer(回滚指针),回滚指针形成版本链

readview: 快照,在版本链中找到合适的版本

假设:
1. 事务 A 开始前,系统里面已经提交的事务最大 ID 是 99;
2. 事务 A、B、C 的版本号分别是 100、101、102,且当前系统里没有别的事务;
3. 三个事务开始前,(1,1)这一行数据的 row trx_id 是 90。
这样,事务 A、B、C 的 up_limit_id 的值就都是 99。
事务 A 要来读数据了,它的 up_limit_id 是 99。当然了,读数据都是从当前版本读起
的。所以读数据流程是这样的:
找到 (1,3) 的时候,判断出 row trx_id=101 大于 up_limit_id,要不起;
接着,找到上一个历史版本,一看 row trx_id=102,还是要不起;
再往前找,终于找到了(1,1),它的 row trx_id=90,是可以承认的数据。

这个主要说明了事务A读取到的值。

那么为什么事务B读到的值是3呢?

这里有两个概念:

当前读:每次都能读到最新的值,

例如,select lock in share mode (共享锁) select for update (排它锁) update(排它锁) insert(排它锁)delete(排它锁) 串行化事务隔离级别

快照读:读到的值是快照里的,例如,普通的select

也就是说每次更新,都要先读后更新,这个读就是当前读,因此值为3;

可重复读解决幻读问题:

快照读解决:

只生成一个readview,一个事务中,同一个版本链中查询结果一致

当前读解决:

使用间隙锁,范围加锁,不会出现两次读的数量不一致

RR和RC的readview有什么不同:

RR:   一个事务只会生成一个readview,查询是在同一个版本链上,结果一致

RC:每一个select都会生成一个readView ,一个事务中,第一次查询以后,进行了更新操作,第二次查询又会生成一个新的readview,导致两次查询出来的结果不一样,不支持可重复读

为什么表结构不支持“可重复读”?这是因为表结构没有对应的行数据,也没
有 row trx_id,因此只能遵循当前读的逻辑。
问题:
事务隔离级别是可重复读。 现在,我要把所有“字段 c 和 id 值相等的行”的 c 值清零,但是却发现了一个“诡异”的、改 不掉的情况,请你构造出这种情况,并说明其原理
CREATE TABLE `t` (
 `id` int(11) NOT NULL,
 `c` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, c) values(1,1),(2,2),(3,3),(4,4);

 结果:

只要update 之前,另一个事务更新c的值,让id=c条件不成立即可,由于读一致性,读的值不会变

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值