请选择 进入手机版 | 继续访问电脑版
查看: 53|回复: 0

[资料分享] 基于read committed使用解析

[复制链接]

签到天数: 193 天

[LV.7]化身百千

发表于 2019-3-14 20:58:22 | 显示全部楼层 |阅读模式

对于熟悉SQL Server的人来说,在说明这个隔离级别之前,必须先给个提醒:MariaDB/MySQL中的提交读和SQL Server中的提交读完全不一样,MariaDB/MySQL中该级别基本类似于SQL Server中基于快照的提交读。

在SQL Server中,提交读的查询会申请共享锁,并且在查询结束的一刻立即释放共享锁,如果要查询的记录正好被独占锁锁住,则会进入锁等待,而没有被独占锁锁住的记录则可以正常查询。SQL Server中基于快照的提交读实现的是语句级的事务一致性,每执行一次操作事务序列号加1,并且每次查询的结果都是最新提交的行版本快照。

也就是说,MariaDB/MySQL中read committed级别总是会读取最新提交的行版本。这在MySQL的innodb中算是一个术语:"一致性非锁定读",即只读取快照数据,不加共享锁。这在前文已经说明过。

MariaDB/MySQL中的read committed隔离级别下,除非是要检查外键约束或者唯一性约束需要用到gap lock算法,其他时候都不会用到。也就是说在此隔离级别下,一般来说只会对行进行锁定,不会锁定范围,所以会导致幻影读问题。

这里要演示的就是在该级别下,会不断的读取最新提交的行版本数据。

当前示例表ttt的记录如下:

mysql> select * from ttt;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
在会话1中执行:

begin;update ttt set id=100 where id=1;
在会话2中执行:

set @@session.tx_isolation='read-committed';
begin;
select * from ttt;
会话2中查询得到的结果为id=1,因为查询的是最新提交的快照数据,而最新提交的快照数据就是id=1。

+------+
| id   |
+------+
|    1 |
|    2 |
+------+
现在将会话1中的事务提交。

在会话1中执行:

commit;
在会话2中查询记录:

select * from ttt;
+------+
| id   |
+------+
|  100 |
|    2 |
+------+
结果为id=100,因为这个值是最新提交的。

再次在会话1中修改该值并提交事务。

在会话1中执行:

begin;update ttt set id=1000 where id=100;commit;
在会话2中执行:

select * from ttt;
+------+
| id   |
+------+
| 1000 |
|    2 |
+------+
发现结果变成了1000,因为1000是最新提交的数据。

read committed隔离级别的行版本读取特性,在和repeatable read隔离级别比较后就很容易理解。

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /2 下一条

返回顶部