MySql事务隔离级别实现(MVCC)

概述

本文会说明mysql InnoDB引擎如何实现RC和RR

 

预备概念

网上资料很多,我这里描述个大概。主要为下面“看图说话”的涉及到的基础知识做个铺垫

mvcc

多版本控制器,我们知道数据库每一条记录都是启用事务执行的操作。每个记录的值 背后一定有操作的事务ID。

多次更新就会有多个。(事务开始的时候,会和InnoDb的事务系统申请,这个trxId是严格递增的)

所以上面描述下来,心里有个图,每行记录都有一个 row list(每个row记录之前的值和trxId 可以做前滚和后滚)。 

 

两阶段锁

行锁是需要的时候加上,事务结束的时候释放

基于这个原则,我们开发的时候 如果一个大事务里面有涉及加锁的操作,可以放在靠近退出事务的地方

减少并发引起的锁等待时间

 

看图说话

MySql事务隔离级别实现(MVCC)_第1张图片

K初始值=1,我们分析下ABC三个事务在RC和RR下的不同值

宝典规则(重点)

事务启动的时候,会记录一个数组,里面包含所有活跃的事务ID(活跃=生成但是未提交的事务),

还涵盖了一个最大水位值(最大活跃trxId + 1)

不在这个数组里面的 一般是可见的,如果在这个范围内 是自己的那个事务 也是可见

 

RR分析

事务A读到的K=1,事务B读到的K=3

1.事务开始的时候,会生成一个视图(类似一个快照,之后的别的事务提交 我不care),一致性读主要靠这个实现

用上面说的那个就是row trxId要小于数组里面最小值,其他的我不可见 不管了

靠这一点很好解释事务A读到的k=1,启动的时候B和C都没执行commit

2.但是按1说的有个奇怪的地方B在update的时候,应该是没法读到事务C的更新后的值的。

这里说明下,每次更新操作会读最新值(不然会覆盖别的事务的更新),这里还有一个绕的地方

事务C的更新操作先执行,事务B执行更新的时候C还没有提交,这个时候B等待最新读的记录。一致要等到C提交释放了写锁,才能拿到值

 

还有两个操作,执行查询加S锁或者X锁 也会当前读

select * from t where id = 1 lock in share mode;

select * from t where id = 1 for update;

 

RC分析

事务A读到的k=1,事务B读到的K=3

每次sql执行前都会建一个视图

 

补充几个有意思的场景

更新一万条数据

第一种,直接执行 delete from T limit 10000; (大事务,锁的时间长 导致主从延迟)

第二种,在一个连接中循环执行 20 次 delete from T limit 500;(优)

第三种,在 20 个连接中同时执行 delete from T limit 500;(锁冲突)

 

你可能感兴趣的:(mysql,mysql)