差点掉坑,MySQL一致性读原来是有条件的

众所周知,在设定了隔离等级为Repeatable Read及以上时,InnoDB 可以实现数据的一致性读。换句话来说,就是事务执行的任意时刻,读取到的数据是同一个快照,不会受到其他事务的更新影响。

以前一直以为在事务内读到的数据不会受其他事务影响,后来发现只有普通的select语句才是一致性读。如果是update, delete, select for update, select in share mode等语句是当前读,读的是数据库最新数据, 下面是两个例子。

加锁读

创建一个测试用的表, 然后插入一条测试用的数据


create table test_innodb_read(
    id int not null primary key,
    value int
) engine = InnoDB charset=utf8;
insert into test_innodb_read values (1, 1);

当前autocommit和隔离等级如下


db83-3306>>select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

db83-3306>>select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)

然后开启两个 Session,分别执行以下操作

时间点 SessionA 结果 SessionB
1 begin
select * from test_innodb_read where id=1
1
2 update test_innodb_read set value = 2 where id=1
3 select * from test_innodb_read where id=1 1
4 select * from test_innodb_read where id=1 lock in share mode 2

由于设置了自动提交,所以SessionB的更新语句执行完就已经提交了,从结果可以看到普通的Select不受其他事务影响,所以读到的数据都是同一版本,而在加锁读的情况下采取的是读最新的数据,所以读到的数据是最新提交的数据。

DML 操作

在进行数据变更操作的时候,也会拿到最新的数据,用的还是上面的表,插入一条测试数据


insert into test_innodb_read values (2, 1);

然后开启两个 Session,分别执行以下操作,

时间点 SessionA 结果 SessionB
1 begin
select * from test_innodb_read where id=2
1
2 update test_innodb_read set value = 2 where id=2
3 select * from test_innodb_read where id=2 1
4 update test_innodb_read set value=value+1 where id=2
5 select * from test_innodb_read where id=2 3

SessionA在时间点 5 查看数据拿到的是 3 而不是 2,原因是,事务在对数据进行更新操作时(时间点4),会先读取一次数据,这次读取的不是事务开始版本,而是数据的最新提交的值 2。如果不读取最新数据的话,就等于覆盖了SessionB的更新,所以读到的是 2,最后得到的数据是 3。

最后

当我知道这个知识点后,感觉背后一凉,以前写代码的时候,喜欢在事务里先把数据查出来,内存中相加减,再存库,现在想想这样做就是BUG啊,坑...

不得不说,极客时间上面的这个MySQL课程还是很值的,至少让我推翻了以前的想法

MySQL实战45讲-8 事务到底是隔离的还是不隔离的

来源:https://segmentfault.com/a/1190000017539522

原文地址:https://www.cnblogs.com/lalalagq/p/10229196.html

时间: 2024-10-09 20:28:02

差点掉坑,MySQL一致性读原来是有条件的的相关文章

MySQL 一致性读 深入研究 digdeep博客学习

http://www.cnblogs.com/digdeep/p/4947694.html 一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文档:http://dev.mysql.com/doc/refman/5.6/en/innodb-consistent-read.html A consistent read means that InnoDB uses multi-versioning to present to a query a

[译]MySQL不加锁实现一致性读的机制分析

原文直通车:Consistent Nonlocking Reads   MySQL的一致性读的机制是是这样实现的:InnoDB引擎为一个事务Tx提供一个在时间T1的版本快照(T1就是在本 事务中首次执行查询语句的时间点).事务Tx中可以查询到时间点T1之前提交的数据,时间点T1之后提交的数据在 Tx中是看不到的.唯一的例外Ex是在事务Tx中可以看到在本事务中提交的数据(即便是在T1时间点还没有提交的数据).   先建一个表,边理论边实践,具体看下MySQL是如何工作的. mysql> creat

MySQL半一致性读原理解析-从源码角度解析

1.什么是半一致性读 A type of read operation used for UPDATE statements, that is a combination of read committed and consistent read. When an UPDATE statement examines a row that is already locked, InnoDB returns the latest committed version to MySQL so that

Docker 从入门到掉坑

简单的对docker进行介绍,可以把它理解为一个应用程序执行的容器.但是docker本身和虚拟机还是有较为明显的出入的.我大致归纳了一下,可以总结为以下几点: docker自身也有着很多的优点,关于它的优点,可以总结为以下几项: 安装docker 从 2017 年 3 月开始 docker 在原来的基础上分为两个分支版本: Docker CE 和 Docker EE. Docker CE 即社区免费版,Docker EE 即企业版,强调安全,但需付费使用. 首先我们需要移除旧的docker版本:

ORACLE 物理读 逻辑读 一致性读 当前模式读总结浅析

在ORACLE数据库中有物理读(Physical Reads).逻辑读(Logical Reads).一致性读(Consistant Get).当前模式读(DB Block Gets)等诸多概念,如果不理解或混淆这些概念的话,对你深入理解一些知识无疑是一个障碍,但是这些概念确实挺让让人犯晕的.下面我们总结.学习一下这方面的知识点.捋一捋他们的关系和特点,希望对你有所帮助. 物理读(Physical Reads) 从磁盘读取数据块到内存的操作叫物理读,当SGA里的高速缓存(Cache Buffer

oracle构建一致性读

对于实际的业务系统,通常有一些热点的表,insert和delete的量非常大,这个时候就会发现一些查询语句的逻辑读比较偏高,这时可能就是oracle在构建一致性块的进行的consistent read.下面做一个测试看下:第一步准备数据: create table test( col1 varchar2(12) col2 number ext varchar2(4000) ); create index test_ind on test(user_id, col2); create sequen

oracle一致性读

sql语句执行时,产生一致性读. 什么是逻辑读? cpu在内存中读这些block的过程就叫做逻辑读(consistent get),在读的过程中产生的IO就是逻辑IO.逻辑读的过程中,是非常消耗cpu资源的.因此,执行sql的逻辑读越少越好.sql调优必须调整buffer get很大的sql语句 logical reads= consistent gets + db block gets,逻辑读其实是DB BLOCK GETS 和 consistents Gets 之和 DB block get

ORACLE 一致性读原理记录

什么是一致性读? 一致性读指的是在从查询那一刻起,中间的变化不予理会. 举例说明 比如我有两个帐户A,B. A 有1000块,B有1000快.我查询的时候查询速度比较慢.中间A转500到B账户. 已经查询到A账户有1000,B账户有1500,这个时候我查询的结果是查询的结果应该是2500还是2000呢? 正确结果当然是2000. 这里就设计到oracle一致性查询的问题了.   oracle有两个概念: 1.SCN,SYSTEM CHANGE NUMBER ,这是一个只会增加的递增数字,存在在O

为啥我老掉坑里

在一个群里看到,码代码除了主线外,还是一个和各种toollist抗争的过程. 和一个同学聊到,工资只是零花钱,一定要习得赚取生活费的技能. 被一个同学问到,两个方向或者两个问题的冲突,除了资源互斥,还有时间线上的不可逆转冲突. 这几天跟中了邪似的,每次我想做正事的时候,例如修改程序,看游戏代码,总是会被意料之外的事情给打断,这种正事无法启动的情况十分打击我的积极性... 例如刚打开vs,发现昨天手误点到的更新导致今天出错,之后又修复vs,修复vs的时候,发现源文件已删除:不小心修改了平台工具集,