博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL REPEATABLE-READ && 幻读
阅读量:6003 次
发布时间:2019-06-20

本文共 4533 字,大约阅读时间需要 15 分钟。

hot3.png

MySQL REPEATABLE-READ && 幻读

关于mysql命令行中事务控制的语句见该文章

关于MVCC多版本控制

表结构

create table t1(    a int primary key,    b int not null    )

 

REPEATABLE-READ可重复读(一)

这里打开两个mysql的命令行窗口,窗口A,即session1,窗口B,即session2。

session1

mysql> begin ;Query OK, 0 rows affected (0.00 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 |+----+------+4 rows in set (0.00 sec)

以上sql只是显示的开启了事务,执行了sql查询。下面看session2的操作。

要注意这里的select操作是一般的快照读。根据MVCC多版本控制规则读取的数据行。

session2

mysql> begin ;Query OK, 0 rows affected (0.00 sec)mysql> insert into t1 values (55, 3000);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.03 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 || 55 | 3000 |+----+------+5 rows in set (0.00 sec)

session2插入了一条数据,并显式的提交了事务。

session1

此时返回session1进行以下操作

mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 |+----+------+4 rows in set (0.00 sec)

此时,虽然在session2中插入了一条数据,并且提交了事务,但在session1中的查询和session1的上次查询还是同一个结果,这就是重复读。(也可以说是根据MVCC规则读取的数据行)。如果是在"READ-COMMITTED"级别下是可以读到a=55这条记录的(因为session2在刚才已经提交了事务)。

 

REPEATABLE-READ可重复读(二)

session1

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t1 where a = 56;+----+------+| a  | b    |+----+------+| 56 | 7000 |+----+------+1 row in set (0.00 sec)

session1,开启了一个事务,查询a = 56 的记录。

session2 

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> update t1 set b = 8000 where a = 56;Query OK, 1 row affected (0.00 sec)Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from t1 where a = 56;+----+------+| a  | b    |+----+------+| 56 | 8000 |+----+------+1 row in set (0.00 sec)mysql> commit    -> ;Query OK, 0 rows affected (0.04 sec)

session2开启了事务,更新a = 56 的记录,同时查询a = 56 的记录,可以看到在同一事务内重复读的效果。

session1

mysql> select * from t1 where a = 56;+----+------+| a  | b    |+----+------+| 56 | 7000 |+----+------+1 row in set (0.00 sec)

和上次查询结果一致,验证了重复读。还是要注意这里的select操作只是一般的快照读。其实不管session2 做什么操作,这里的快照读都是重复读的。

此时,如果session1提交该事务,重新开启事务,查询能查到session2中修改的结果

mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> select * from t1 where a = 56;+----+------+| a  | b    |+----+------+| 56 | 8000 |+----+------+1 row in set (0.00 sec)

注:以上的重复读,虽然在当前事务中真的是重复读的现象,但到底来说是通过MVCC多版本控制实现的可重复读。

 

REPEATABLE-READ与幻读

session1 

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 || 55 | 4000 || 56 | 8000 |+----+------+6 rows in set (0.00 sec)

开启事务,select操作为快照读。

session2

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 || 55 | 4000 || 56 | 8000 |+----+------+6 rows in set (0.00 sec)mysql> insert into t1 values (57, 1000);Query OK, 1 row affected (0.00 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 || 55 | 4000 || 56 | 8000 || 57 | 1000 |+----+------+7 rows in set (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.11 sec)

在session2 中做了一系列的操作,插入insert,这里其实是当前读(写入)。然后提交事务。

session1 

mysql> update t1 set b = b+1000;Query OK, 7 rows affected (0.00 sec)Rows matched: 7  Changed: 7  Warnings: 0mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 4000 || 52 | 4000 || 53 | 4000 || 54 | 4000 || 55 | 5000 || 56 | 9000 || 57 | 2000 |+----+------+7 rows in set (0.00 sec)

session1做更新操作,这里更新成功。如果session2 插入记录后,没有提交事务,这里更新是要阻塞的,因为session2 插入记录持有那条记录的X锁。

session1整个会话的sql

mysql> begin;Query OK, 0 rows affected (0.00 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 || 55 | 4000 || 56 | 8000 |+----+------+6 rows in set (0.00 sec)mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 3000 || 52 | 3000 || 53 | 3000 || 54 | 3000 || 55 | 4000 || 56 | 8000 |+----+------+6 rows in set (0.00 sec)mysql> update t1 set b = b+1000;Query OK, 7 rows affected (0.00 sec)Rows matched: 7  Changed: 7  Warnings: 0mysql> select * from t1;+----+------+| a  | b    |+----+------+| 51 | 4000 || 52 | 4000 || 53 | 4000 || 54 | 4000 || 55 | 5000 || 56 | 9000 || 57 | 2000 |+----+------+7 rows in set (0.00 sec)mysql>

可以看到多出了一行,这算是幻读吗?其实不是。这是根据MVCC的select规则读出来的数据

请详见

 

总结:

REPEATABLE READ:在mysql中,不会出现幻读。mysql的实现和标准定义的RR隔离级别有差别。

==========END==========

转载于:https://my.oschina.net/xinxingegeya/blog/296513

你可能感兴趣的文章
Makefile 多目录自动编译
查看>>
学习笔记:Oracle dul数据挖掘 导出Oracle11G数据文件坏块中表中
查看>>
统一Matlab下不同子图的色标colorbar
查看>>
Linux 进程间通信(二) 管道
查看>>
深入浅出JQuery (二) 选择器
查看>>
CI框架 -- 驱动器
查看>>
FastMQ V0.2.0 stable版发布
查看>>
对象复制
查看>>
Mongodb内嵌数组的完全匹配查询
查看>>
WARN hdfs.DFSClient: Caught exception java.lang.InterruptedException
查看>>
移动硬盘文件或目录损坏且无法读取怎么解决
查看>>
在shell中使用sed命令替换/为\/
查看>>
JavaSe: 不要小看了 Serializable
查看>>
Node.js 抓取电影天堂新上电影节目单及ftp链接
查看>>
linux popen函数
查看>>
[游戏开发]关于手游客户端网络带宽压力的一点思考
查看>>
如何成为强大的程序员?
查看>>
How To: 用 SharePoint 计算列做出你自己的KPI列表
查看>>
Visual Studio下使用jQuery的10个技巧
查看>>
web服务器工作原理及http协议通信
查看>>