读可重复隔离级别下多session ddl操作的事务隔离与可见问题一例

研究mysql45讲时的又一个实验,灵感来自08讲的思考题。多session下可能会造成的不一致问题。过程如下

实验条件:Mysql,innoDB

表t初始数据如下

 

id

c

Line1

1

1

Line2

2

2

Line3

3

3

Line4

4

4

实验步骤如下

时刻

Session1

Session2

1

start transaction with consistent snapshot;

/*开启事务并在开启时开一致性视图*/

 

2

 

Update t set c=c+1;

/*在另一个session中把表更新了,此时表中存储的c值:2,3,4,5*/

3

Select * from t;

/*由于一致性视图,后面更新的内容在之前的session中是不认账的,这里查到的c值仍为1,2,3,4*/

 

4

Update t set c=0 where c=3;

/*概念1:“当前读”,虽然使用了可重复读隔离级别,但为了防止数据增删改操作丢失,这些操作会先读取最新版本的值而后在最新值上直接进行操作,因此被修改的实际上是line2 (2,3)->(2,0)

*/

 

5

 

Select * from t;

/*严格来说这里用这一句相当于又开了一个session,该算作session3的,不好排版所以搁这儿了

此时c值:2,3,4,5因为session1还没提交。假设再在session1外有其他update操作,那么由于session1使用update操作过了这张表,两阶段锁,排队等待session1提交或回滚。(这个update无论想改的是line2还是line1,3,4都得等着)*/

6

Select * from t;

/*概念2:一致性视图对于后面更新的内容虽然不认账,但对于自己更新的内容是要认的,即是说line1,3,4仍然保持开启事务时的一致性读状态,而自己修改过的line2则是最新状态。

此时查询到的c值为1,3,3,4

*/

 

具体结果也截个图吧

 

 

附上原问题与我觉着很赞的一篇分析过程

我用下面的表结构和初始化语句作为试验环境,事务隔离级别是可重复读。现在,我要把所有“字段 c 和 id 值相等的行”的 c 值清零,但是却发现了一个“诡异”的、改不掉的情况。请你构造出这种情况,并说明其原理。
mysql> 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);

@lucky star  7
答案:
分析: 假设有两个事务A和B, 且A事务是更新c=0的事务; 给定条件: 1, 事务A update
语句已经执行成功, 说明没有另外一个活动中的事务在执行修改条件为id in 1,2,3,4或c in 1,
2,3,4, 否则update会被锁阻塞; 2,事务A再次执行查询结果却是一样, 说明什么?说明事务
B把id或者c给修改了, 而且已经提交了, 导致事务A“当前读”没有匹配到对应的条件; 事务
A的查询语句说明了事务B执行更新后,提交事务B一定是在事务A第一条查询语句之后执行
的;
所以执行顺序应该是:
1, 事务A select * from t;
2, 事务B update t set c = c + 4; // 只要c或者id大于等于5就行; 当然这行也可以和1调换,
不影响
3, 事务B commit;
4, 事务A update t set c = 0 where id = c; // 当前读; 此时已经没有匹配的行
5, 事务A select * from t;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值