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一致性读原来是有条件的
众所周知,在设定了隔离等级为Repeatable Read及以上时,InnoDB 可以实现数据的一致性读.换句话来说,就是事务执行的任意时刻,读取到的数据是同一个快照,不会受到其他事务的更新影响. 以 ...
- [MySQL] 一致性读分析
MySQL MVCC MySQL InnoDB存储引起实现的是基于多版本的并发控制协议---MVCC(Multi-Version Concurrency Control),基于锁的并发控制,Lock- ...
- MySQL 一致性读 深入研究
一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文档:http://dev.mysql.com/doc/refman/5.6/en/innod ...
- MySQL 一致性读 深入研究 digdeep博客学习
http://www.cnblogs.com/digdeep/p/4947694.html 一致性读,又称为快照读.使用的是MVCC机制读取undo中的已经提交的数据.所以它的读取是非阻塞的. 相关文 ...
- mysql一致性读
Consistent Nonlocking Reads 一致读意味着InnoDB用多版本来提供一个查询数据库某个时间点的快照.这种查询可以看到在当前世界点之前事务提交的改变,看不到此后提交的改变,更看 ...
- MySQL一致性非锁定读
一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(multi versionning)的方式来读取当前执行时间数据库中行的数据,如果读取的行 ...
- MySQL的默认隔离级别的实现依赖于MVCC和锁,准确点说就是一致性读和锁。
MySQL的默认隔离级别的实现依赖于MVCC和锁,准确点说就是一致性读和锁.
- MySQL——一致性非锁定读(快照读)&MVCC
MySQL--一致性非锁定读(快照读) MySQL数据库中读分为一致性非锁定读.一致性锁定读 一致性非锁定读(快照读),普通的SELECT,通过多版本并发控制(MVCC)实现. 一致性锁定读(当前读) ...
- MySQL事务(二)事务隔离的实现原理:一致性读
今天我们来学习一下MySQL的事务隔离是如何实现的.如果你对事务以及事务隔离级别还不太了解的话,这里左转. 好的,下面正式进入主题.事务隔离级别有4种:读未提交.读提交.可重复读和串行化.首先我们来说 ...
随机推荐
- Eolink家族成员回归 — 开源服务Eoapi!
Eolink 开源产品又回来了!Eoapi 自 2016 年上架 Github 以来,一直备受国内外开发者的欢迎和好评 ,在2018年 Eolink 为了进一步升级该产品而进行了暂时下架.时隔四年,E ...
- 【干货】MySQL底层架构设计,你了解多少?
很多开发同学对SQL优化如数家珍,却对MySQL架构一知半解.岂不是只见树叶,不见森林,终将陷入细节中不能自拔. 今天就一块学习MySQL分层架构,深入了解MySQL底层实现原理,以及每层的作用,我们 ...
- RabbitMQ消费者消失与 java OOM
原因: 下午先是收到钉钉告警有一个消费者系统任务积压, 当时以为就是有范围上量没有当回事,后来客服群开始反馈说有客户的数据没有生成.这个时候查看mq的后台,发现任务堆积数量还是很多. 这个时候登录一台 ...
- python操作ini文件
简介 ini文件作为常见的配置文件,因此需要对ini文件做处理,此处使用configparser模块,本文介绍以下ini文件常用的处理方式. 需要读取的ini文件 如下文件,[ ]包含的称为secti ...
- Vue中computed用法
computed是什么?对于任何复杂逻辑,你都应当使用计算属性.computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义.然后就可以在页面上进行双向数据绑定展 ...
- PHP及相关服务器防盗链
服务器防盗链 假设域名为www.localhost.com 1.apache配置httpd.conf SetEnvIfNoCase Referer "^http://www.localhos ...
- 1. MGR简介 | 深入浅出MGR
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1. 为什么是MGR MGR是MySQL Group Replication的缩写,即MySQL组复制. 在以往,我们一般 ...
- SvelteUI:运用svelte3构建的网页版UI组件库(升级版)
距离上次分享的svelte-ui 1.0已经一月有余,这次带来全新升级完整版svelte-ui 2.0. 这次优化并新增15+个组件.在开发之初借鉴了element-ui组件库,所以在组件结构及语法上 ...
- 在DispatcherServlet.class中的,获取方法值中获取到的都是arg值
原先java虚拟机中在编译是不带着方法的形参的名称,但是在jdk8中是可以带了 只需要在Settings中设置以下: -parameters 再把out文件中的production文件删到在查询bui ...
- 从原理剖析带你理解Stream
摘要:Stream是jdk1.8给我们提供的新特性 本文分享自华为云社区<深入理解Stream之原理剖析>,作者: 李哥技术 . Stream是jdk1.8给我们提供的新特性,主要就是允许 ...