龙空技术网

MySQL中的一致性快照读、当前读

程序猿集锦 47

前言:

目前我们对“mysql快照表”可能比较讲究,姐妹们都需要分析一些“mysql快照表”的相关知识。那么小编也在网摘上汇集了一些关于“mysql快照表””的相关内容,希望大家能喜欢,咱们一起来学习一下吧!

关注我「程序猿集锦」获取更多分享。

背景准备实验环境实验步骤总结背景

你应该听到过有人说到过这样的名词:快照读、当前读这样的名词。那么你理解他们口中所谓的快照读、当前读具体是什么含义吗?

下面这篇文章就带你体验一下什么是快照读?什么是当前读?

准备实验环境

创建一个InnoDB存储引擎的表,并初始化的插入2行数据,语句如下所示:

drop table if exists t;create table t(id int primary key, v int);insert into t values(1,1);insert into t values(2,2);select * from t;

MySQL的版本是5.7,事务的隔离级别是Repeatable Read可重复读事务隔离级别。

实验步骤

我们先看实验,再说什么时候快照读、当前读就很好理解了。

时刻

事务A

事务A的释义

事务B

事务B的释义

T1

begin;

开启一个事务A

begin;

开启一个事务B

T2

select * from t;

查询表t中所有的数据内容,

此时事务A可以查看到2条

初始化的数据

select * from t;

查询表t中所有的数据内容,

此时事务B可以查看到2条

初始化的数据

T3

update t set v = v + 1;

修改表t中所有的数据,把a列的值都在原先a的值的基础上增加1.

T4

select * from t;

查询表t中所有的数据内容,

此时事务A可以查看到2条

初始化的数据,

此时的数据和事务A在T2时刻

查询到的数据内容是一致的。

select * from t;

查询表t中所有的数据内容,

此时事务B可以查看到2条数据,

此时的数据和事务B在T2时刻

查询到的数据内容是不相同的,

是事务B修改后的数据内容。

T5

commit;

事务B提交

T6

select * from t;

查询表t中所有的数据内容,

此时事务A可以查看到2条

初始化的数据,

此时的数据和事务A在T2时刻

查询到的数据内容是一致的。

T7

update t set v=100 where id = v;

此时事务A更新所有的数据,

条件是 id = v,但是发现更

新的时候输出的受影响行数

为0行,明明有2条数据,为何不能更新成功呢?输入如下所示:

Query OK, 0 rows affected (0.01 sec)

Rows matched: 0 Changed: 0 Warnings: 0

上面的过程中,T2时刻的读,不管是对事务A还是对于事务B来说,都称之为快照读,也叫做一致性快照读。同样的,T4T6时刻对于事务A来讲,也是快照读;但是在T3时刻和T7时刻都有一个update的操作,此时的操作称之为当前读

你可能会有疑问:这不是更新的update操作吗?怎么还涉及到当前读了呢?不要忘记更新操作需要先查询出来再基于查询传来的结果上进行更新,而这个查询的动作,就称之为当前读。

常见的当前读主要体现在以下SQL语句中:

select * from t where id = xx lock in share mode;select * from t where id = xx for update;insert into t values(x,x);update t set v=xx where id = xx;delete from t where id > 1;

现在我们来分析一下为什么事务AT7时刻尝试更新数据的时候,总是更新不成功,但是在T6时刻去查询的时候,得到的结果却是有待更新的结果集的。

T6时刻的读是一致性快照读,它读取的并不一定是数据库中最新的已经提交的数据的内容,而是从T2时刻开始的那一刻数据库中表t中的数据状态。此后,只要是在事务A中涉及到的快照读的时候,都会使用T2时刻事务A读取到的数据版本。如果其他事务对表t中的数据做了修改,事务A也不去读取最新的已经提交数据,因为事务A在执行的过程中要满足RR事务隔离级别下,可以重复读取数据的要求,所以它才会一直使用事务AT2时刻读取的数据内容快照。T7时刻的读是当前读,之所以要采用当前读,而不是采用快照读是因为,更新的操作,要基于数据库中最新已经提交的数据进行更新,如果基于原先事务AT2时刻读取到的数据内容去做更新,就会把事务BT3时刻更新后已经提交的数据给覆盖掉了,也就是导致了我们平时所说的更新丢失问题的发生。所以,事务AT7时刻要用当前读,去读取最新的已经提交的数据再去做事务A自己的修改操作,这样就可以避免更新丢失现象的发生。总结

现在你应该可以理解什么是快照读、什么是当前读了。

快照读:一个事务在它执行的过程中,在查询数据的时候,总是查询到这个事务启动时刻数据库中的数据的版本,而不会关心数据在它启动后,是否有被其他事务更新或删除。以保证在这个事务执行的整个周期内,可以满足它可重复读的需求,避免不可以重复现象的发生。这个功能实现是通过MVCC机制来实现的。当前读:一个事务在它执行的过程中,在查询数据的时候,总是查询到数据库中的最新的数据版本,而不会关心在这个事务启动时数据库中数据版本。以保证在这个事务执行更新或删除操作的时候,能够基于最新的(已经提交的)数据版本之上进行,避免发生更新丢失现象的凡是。

关注我「程序猿集锦」获取更多分享。

标签: #mysql快照表