[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)实现. 一致性锁定读(当前读) ...
随机推荐
- 03-Mysql数据库----安装与管理
本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的 ...
- 怎么用Q-Q图验证数据集的分布
样本数据集在构建机器学习模型的过程中具有重要的作用,样本数据集包括训练集.验证集.测试集,其中训练集和验证集的作用是对学习模型进行参数择优,测试集是测试该模型的泛化能力. 正负样本数据集符合独立同分布 ...
- 常量表达式 & constexpr
[常量表达式] 一个这样的表达式:值不会改变 && 在编译过程中就能够得到计算结果 常见的常量表达式:字面值.用常量表达式初始化的const对象 一个对象是不是常量表达式由它的数据类型 ...
- http长连接和短连接以及连接的本职
HTTP长连接和短连接原理浅析 本文主要讲了,http长连接本质是tcp的长连接. 网络通信过程中,建立连接的本质是什么? 连接的本质 建立连接这个词,是从早期的电话系统中来的,那个时候,“建立连接” ...
- 微信小程序—setTimeOut定时器的坑
原文地址: http://fanjiajia.cn/2018/06/27/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E2%80%94setTimeOu ...
- Vue组件间通信:一个例子学会Vue组件-Vue.js学习总结)(转载)
详情请点击 http://www.jianshu.com/p/9ad1ba89a04b
- Delphi xe7组件和控件的安装方法
暂时我所遇到的所有控件安装方法大体与下面两种相同. 若有不同大家提出来,一起想办法解决. .dproj格式的组件安装方法: raise组件 安装详细步骤如下: 一.设置搜索路径1. 将本包中的文件连同 ...
- 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap
题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义 ...
- java8 增强的Iterator遍历集合元素
Iterator接口也是Java集合框架的成员,与Collection和Map两个系列的集合不一样的是Collection和Map系列主要用于充当容器的作用,而Iterator正如其名字一样是主要用于 ...
- 利用FFT来进行字符串匹配
给定串A和串B,A由26个小写字母构成,B由?和26个小写字母构成 ?可以和任意字符匹配 求A中出现了多少次B 这里可以使用fft做法,定义向量A和向量B 然后求A和rev(B)的卷积结果C C的第i ...