原文地址:事务到底是隔离的还是不隔离的?
我们之前学习了隔离级别和锁,在隔离级别里有一个可重复读,锁里有个行锁。
- 可重复读:事务期间,看不懂别的事务的更新;
- 行锁:有事务 1 在更新某行数据时,若有其他事务 2 进来,会被锁住
矛盾来了:事务 2 等待结束,获取到行锁时,看到的是哪个数据呢?
按可重复读隔离级别来说,看到的应该是事务启动时的最新数据,即事务 1 修改之前的数据;
但是这样不就造成了事务 1 的修改丢失了吗?
本文脑图:https://mubu.com/doc/hyPYP01r-G
话不多说,我们先手动实验一把。
实验
我们建个表先:
mysql> CREATE TABLE `t` (
`id` int(11) NOT NULL,
`k` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);
然后做如下操作:
说明:
1、begin/start transaction 运行后其实并不会立即启动事务,执行第一个操作 InnoDB 表的语句时才会真正启动;
2、显示启动事务:start transaction with consistent snapshot
很容易看到实验结果:
- A 读到的值是 1
- B 读到的值是 3
看上去 B 事务违反了可重复读隔离级别的概念,为啥呢?
原因探索
之前在学习事务隔离级别时,我们接触到了一个「视图」的概念,这个视图和我们平常接触的 view 视图并不一样。
MySQL 中的两个「视图」的区别
一、常说的视图:view
① 是用查询语句定义的虚拟表;
② 在调用时执行查询,并生成结果;
③ 创建方法:create view...
;
二、MVCC 中的一致性视图(consistent read view)
① 用于支持隔离级别的实现:RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)
② 没有物理结构,作用是事务执行期间用来定义我能看到什么数据;
③ 其中,可重复读:每个事务启动是都会重建读视图,整个事务存在期间都用这个视图;
快照是什么
很多文章都会说可重复读隔离级别下