[MySQL] 一致性读分析
MySQL MVCC
MySQL InnoDB存储引起实现的是基于多版本的并发控制协议---MVCC(Multi-Version Concurrency Control),基于锁的并发控制,Lock-Based Concurrency Control。
一致性读,又称快照读,读取的是undo中已提交的数据,可能是数据的历史版本,no-locking,所以是非阻塞的读取操作。
A consistent read means that InnoDB uses multi-versioning to present to a query a snapshot of the database at a point in time. The query sees the changes made by transactions that committed before that point of time, and no changes made by later or uncommitted transactions. The exception to this rule is that the query sees the changes made by earlier statements within the same transaction.
那么一致性读(快照读)和当前读有什么区别呢?
snapshot read:
读取记录的可见版本(有可能是历史版本), no-locking
no-locking reads: 简单的select语句
- select..
current read:
读取的是记录的最新版本, 加锁保证事务隔离性
locking-reads: 特殊操作, 插入/更新/删除操作
- select .. for update
- select ... in share mode
- insert
- update
- delete
RC隔离和RR隔离的中的一致性读
Case1:RR隔离
对于RR的事务隔离级别,同一个事务所有的一致性读建立在第一次read操作开始时。
If the transaction isolation level is REPEATABLE READ (the default level), all consistent reads within the same transaction read the snapshot established by the first such read in that transaction.
深入理解下"the first such read in that transaction"这句话,事务开始后,对表的第一次select语句建立了该事务中一致性读的snapshot,而并非指事务的begin或者start transaction。

上面的实验说明:RR隔离级别下的一致性读,不是以begin为开始建立的snapshot,而是第一条select语句为timepoint建立的snapshot。

上面的实验说明:RR隔离级别下的一致性读,是以第一条select语句为timepoint建立的snapshot,即使是针对不同的表做检查。

上面的实验说明:RR隔离级别下,其他事务插入的数据,即使没有提交,在本事务中也可以update成功,因为update语句执行的是“当前读”,并且修改后的数据在本事务中可见。
最后,在RR隔离级别下,locking reads的加锁信息依赖于具体的SQL条件,如果基于UK的唯一搜索条件,那么会锁定二级uk index记录以及聚簇索引表的记录(no-gap锁);如果基于范围区域的扫描条件,那么会锁定记录本身外,还会使用gap locks/next-key lock来避免幻读。具体可参考"MySQL 加锁处理分析"
Case2:RC隔离
对于RC事务隔离级别,每一个一致性读都是最新的快照数据。
With READ COMMITTED isolation level, each consistent read within a transaction sets and reads its own fresh snapshot.
MySQL中事务开始时间
一般的begin/start transaction是事务开始的时间点,这里有误区,正如上面的实验看到的。事务开始的真正时间点(LSN)是start transaction之后执行的第一条语句。
START TRANSACTION WITH consistent snapshot指执行start transaction同事建立事务的一致性读snapshot。
The WITH CONSISTENT SNAPSHOT modifier starts a consistent read for storage engines that are capable of it. This applies only to InnoDB. The effect is the same as issuing a START TRANSACTION followed by a SELECT from any InnoDB table. See Section 14.2.2.2, “Consistent Nonlocking Reads”. The WITH CONSISTENT SNAPSHOT modifier does not change the current transaction isolation level, so it provides a consistent snapshot only if the current isolation level is one that permits a consistent read. The only isolation level that permits a consistent read is REPEATABLE READ. For all other isolation levels, the WITH CONSISTENT SNAPSHOT clause is ignored. As of MySQL 5.7.2, a warning is generated when the WITH CONSISTENT SNAPSHOT clause is ignored.
一致性读问题
一致性读在遇到特定的DDL语句的问题
Consistent read does not work over certain DDL statements
- drop table语句,因为MySQL是无法使用一个已经被drop的表。
- alter table语句,因为alter table会通过表copy的方式实现,在一致性读开始后,alter table过程中的临时表数据是无法看到的,这种情况下,事务会返回:ER_TABLE_DEF_CHANGED(Table definition has changed, please retry transaction)。
这个问题经常发生在mysqldump一致性备份期间。
一致性mysqldump问题
mysqldump是MySQL逻辑数据导出的有力工具,其中参数:--single-transaction参数支持数据的一致性导出。原理是:设置事务为RR模式,然后获取LSN快照,来获得一致性的数据。
--single-transaction
Creates a consistent snapshot by dumping all tables in a
single transaction. Works ONLY for tables stored in
storage engines which support multiversioning (currently
only InnoDB does); the dump is NOT guaranteed to be
consistent for other storage engines. While a
--single-transaction dump is in process, to ensure a
valid dump file (correct table contents and binary log
position), no other connection should use the following
statements: ALTER TABLE, DROP TABLE, RENAME TABLE,
TRUNCATE TABLE, as consistent snapshot is not isolated
from them. Option automatically turns off --lock-tables.
ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 这些DDL语句的执行,会导致无法使用undo构造出正确的一致性读,一致性读和它们是无法隔离的。
另外在mysqldump中还可能遇到大查询带来的"waiting for table flush"问题, 假设有3个会话,会话A执行大查询,访问t表;然后一个备份会话B正处于关闭表阶段,需要关闭表t;随后会话C也请求访问t表。三个会话按照这个顺序执行,我们会发现备份会话B和会话C访问t表的线程都处于“waiting for table flush”状态。这就是关闭表引起的,这个问题很严重,因为此时普通的select查询也被堵住了。下面简单解释下原因:
- 会话A打开表t,执行中……
- 备份会话B需要清理表t的cache,更新版本号(refresh_version++)
- 会话B发现表t存在旧版本(version != refresh_version),表示还有会话正在访问表t,
等待,加入share对象的等待队列 后续会话C同样发现存在旧版本(version != refresh_version),
等待,加入share对象的等待队列
......大查询执行完毕,调用free_table_share,唤醒所有等待线程。
free_table_share //逐一唤醒所有等待的线程。
{
while ((ticket= it++))
ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED);
}
第4步与第5步之间,所有的访问该表的会话都处于“waiting for table flush”状态,唯有大查询结束后,等待状态才能解除。
参考:
MySQL 5.7官方文档:http://dev.mysql.com/doc/refman/5.7/en/innodb-consistent-read.html
MySQL 加锁处理分析:http://hedengcheng.com/?p=771
FTWRL详解:http://www.cnblogs.com/cchust/p/4603599.html
[MySQL] 一致性读分析的更多相关文章
- 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一致性读原来是有条件的
众所周知,在设定了隔离等级为Repeatable Read及以上时,InnoDB 可以实现数据的一致性读.换句话来说,就是事务执行的任意时刻,读取到的数据是同一个快照,不会受到其他事务的更新影响. 以 ...
- MySQL一致性读原来是有条件的
众所周知,在设定了隔离等级为Repeatable Read及以上时,InnoDB 可以实现数据的一致性读.换句话来说,就是事务执行的任意时刻,读取到的数据是同一个快照,不会受到其他事务的更新影响. 以 ...
- mysql一致性读
Consistent Nonlocking Reads 一致读意味着InnoDB用多版本来提供一个查询数据库某个时间点的快照.这种查询可以看到在当前世界点之前事务提交的改变,看不到此后提交的改变,更看 ...
- MySQL一致性非锁定读
一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(multi versionning)的方式来读取当前执行时间数据库中行的数据,如果读取的行 ...
- 6. SOFAJRaft源码分析— 透过RheaKV看线性一致性读
开篇 其实这篇文章我本来想在讲完选举的时候就开始讲线性一致性读的,但是感觉直接讲没头没尾的看起来比比较困难,所以就有了RheaKV的系列,这是RheaKV,终于可以讲一下SOFAJRaft的线性一致性 ...
- MySQL的默认隔离级别的实现依赖于MVCC和锁,准确点说就是一致性读和锁。
MySQL的默认隔离级别的实现依赖于MVCC和锁,准确点说就是一致性读和锁.
- MySQL——一致性非锁定读(快照读)&MVCC
MySQL--一致性非锁定读(快照读) MySQL数据库中读分为一致性非锁定读.一致性锁定读 一致性非锁定读(快照读),普通的SELECT,通过多版本并发控制(MVCC)实现. 一致性锁定读(当前读) ...
随机推荐
- 剑指offer-跳台阶08
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). class Solution: def jumpFloor(self, ...
- python基础训练营02
任务二 时长:2天 1. 列表 a. 标志 b. 基本操作(创建,append( ),pop( ) ,del( ), 拷贝) c. 列表相关方法 2. 元组 a. 标志 b. 基本操作(创建及不可变性 ...
- Leetcode 675.为高尔夫比赛砍树
为高尔夫比赛砍树 你被请来给一个要举办高尔夫比赛的树林砍树. 树林由一个非负的二维数组表示, 在这个数组中: 0 表示障碍,无法触碰到. 1 表示可以行走的地面. 比1大的数 表示一颗允许走过的树的高 ...
- el-checkbox根据是否被选中执行不同的操作
直接给el-checkbox绑定点击事件是没有效果的,因为它会被解析成其他形式的html,el-checkbox只是一个类名,因此,使用ts和jquery动态绑定事件: mounted() { $(& ...
- Chromium多进程资源加载
webkit笔记,主要来自 朱永盛 <WebKit技术内幕> 学习笔记,转载就注明原著,该书是国内仅有的Webkit内核的书籍,学习的好导师,推荐有兴趣的朋友可以购买 多进程 资源的实际加 ...
- 我的python计划
一直想学习一种脚本语言.现在主流的脚本语言,比较先接触的是python 刚开始了解了一下python,感觉挺适合自己的感觉,学习了一段时间,之中感觉,就好象C++一样,把面向对象和面向过程编程结合了起 ...
- C++ 点
2017/12/23 scoped_ptr类型的指针,只能在一个namespace中使用 1) 怎么查看元素在set中是否存在 1) istringstream类用于执行C++风格的串流的输入操作. ...
- could not read column value from result set:
错误描述: INFO [http-apr-8080-exec-26] (NullableType.java:203) - could not read column value from result ...
- HTML5<canvas>标签:使用canvas元素在网页上绘制线条和圆(1)
什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形.字符以 ...
- React生命周期总结
React的生命周期总共8个钩子,三个will,两个Did,一个RecciveProps,一个ShouldUpdate,一个render.分为三个阶段,分别是 装载 Mounting更新 Updati ...