数据库隔离级别 理解

CREATE TABLE `account`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `balance` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
)

1.第一个窗口, 第一次查询

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+----------+---------+
| id | username | balance |
+----+----------+---------+
|  1 | 22       |    1000 |
|  2 | 22       |    1000 |
|  3 | 22       |    1000 |
|  4 | 22       |    1000 |
|  5 | 22       |    1000 |
|  6 | 22       |    1000 |
|  8 | 111      |    1000 |
+----+----------+---------+
7 rows in set (0.00 sec)

2.第二个窗口, 第一次查询

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+----------+---------+
| id | username | balance |
+----+----------+---------+
|  1 | 22       |    1000 |
|  2 | 22       |    1000 |
|  3 | 22       |    1000 |
|  4 | 22       |    1000 |
|  5 | 22       |    1000 |
|  6 | 22       |    1000 |
|  8 | 111      |    1000 |
+----+----------+---------+
7 rows in set (0.00 sec)

3.第一个窗口,改变值(全部变成 33 )并提交

mysql>  update account set username='33';
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

4.第二个窗口第一个窗口改变值后,再次查询,发现没有变化

mysql> select * from account;
+----+----------+---------+
| id | username | balance |
+----+----------+---------+
|  1 | 22       |    1000 |
|  2 | 22       |    1000 |
|  3 | 22       |    1000 |
|  4 | 22       |    1000 |
|  5 | 22       |    1000 |
|  6 | 22       |    1000 |
|  8 | 111      |    1000 |
+----+----------+---------+
7 rows in set (0.00 sec)

5.第二个窗口接着提交,然后在查询,发现值已经变化,保证在事务提交前,读取的都是同一个值,解决不可重复读

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+----------+---------+
| id | username | balance |
+----+----------+---------+
|  1 | 33       |    1000 |
|  2 | 33       |    1000 |
|  3 | 33       |    1000 |
|  4 | 33       |    1000 |
|  5 | 33       |    1000 |
|  6 | 33       |    1000 |
|  8 | 33       |    1000 |
+----+----------+---------+
7 rows in set (0.00 sec)

总结:

事务隔离级别 - 读取未提交 存在 脏读问题

脏读指事务A读取到了事务B更新了但是未提交的数据,然后事务B由于某种错误发生回滚,那么事务A读取到的就是脏数据。

事务隔离级别 - 读取已提交 存在 不可重复读问题

不可重复读就是,有A,B俩事务

B事务进行了一次余额查询结果为1000

这时A事务对这个余额进行了修改,改为500

这时候B事务再去查询,发现余额变为500,这个就是不可重复读

所以为了解决不可重复读,隔离级别就得设置为可重复读Repeated Read。

读取已提交:解决了脏读问题,但是无法做到可重复读,也没办法解决幻读

事务隔离级别 - 可重复读 题 存在 幻读问题

可重复读在提交前,都是读取的同一个值(实际上数据库数据已经被修改了);提交后读取的就是修改后的内容(数据库真实内容)。

可重复读对此基础上,要求A也必须提交事务,才能读取到B修改并提交事务的数据,若A在B修改并提交事务后没有提交事务就去读取,每次的结果都是一样的,但实际B事务已对数据做出成功修改(硬盘中的文件数据以改变),A事务读到的都是备份数据,总感觉出现了幻觉,所以叫幻读!

可重复读:解决不可重复读问题

幻读 VS 不可重复读

幻读重点在于数据是否存在。原本不存在的数据却真实的存在了,这便是幻读。在同一个事务中,第一次读取到结果集和第二次读取到的结果集不同。(对比上面的例子,当B事务INSERT以后,A事务中再进行插入,此次插入相当于一次隐式查询)。引起幻读的原因在于另一个事务进行了INSERT操作。

RR级别下解决幻读问题靠的是锁机制,而不是MVCC机制


不可重复读重点在于数据是否被改变了。在一个事务中对同一条记录进行查询,第一次读取到的数据和第二次读取到的数据不一致,这便是可重复读。引起不可重复读的原因在于另一个事务进行了UPDATE或者是DELETE操作。


简单来说:幻读是说数据的条数发生了变化,原本不存在的数据存在了。不可重复读是说数据的内容发生了变化,原本存在的数据的内容发生了改变。

超深度解析,讲得不错

再探幻读!什么是幻读?为什么会产生幻读,MySQL中是怎么解决幻读的?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值