admin 管理员组文章数量: 1184232
MySQL默认的隔离级别和其他数据库不一样,它默认的是可重复读(Repeatable-Read),其他大部分数据库是读已提交(Read-Commited),为什么会这样呢?先认识一下隔离级别.
认识隔离级别
https://blog.csdn/weixin_43507224/article/details/107183642
各个隔离级别下分别会出现的问题:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 未提交读 | 可能 | 可能 | 可能 |
| 已提交读 | 不可能 | 可能 | 可能 |
| 可重复读 | 不可能 | 不可能 | 可能 |
| 可串行化 | 不可能 | 不可能 | 不可能 |
脏读: 事务A读取到了事务B修改但未提交且最后要回滚的数据。
小明去取钱,小红给小明汇钱,小明输入密码后发现金额100, 小明取走50,在小明取走过程中,小红汇钱给小明 50,小红还没有确定汇款,小明这是拿到50块钱后发现余额还是100; 这时这100块是脏读;
不可重复读: 事务A读取到的数据不一致(两次读取之间有事务B做更新操作)
例如:小明取钱,小红去花小明的钱,小明账户余额100,小明取走50,小明取走后50后查询余额是50,小红手机支付10块,小明再查余额变成40了;
幻读: 事务A读取的结果条数不一致(两次读取之间有事务B做插入数据操作)
A把数据一条数据1改成了2,B同时往数据库中插入了一条1,A再查看的时候 发现1还在;
可串行化严重影响并发性能,用的并不多。那么还剩下幻读的问题没有解决
MySQL为什么用可重复读作为默认隔离级别
这要从主从复制说起:
1.主从复制,是基于什么复制的?
是基于binlog复制的
2.binlog有几种格式?
statement:记录的是修改SQL语句
row:记录的是每行实际数据的变更
mixed:statement和row模式的混合
那Mysql在5.0这个版本以前,binlog只支持STATEMENT这种格式!而这种格式在读已提交(Read Commited)这个隔离级别下主从复制是有bug的,主库和从库因为执行顺序问题,导致数据不一致,因此Mysql将可重复读(Repeatable Read)作为默认的隔离级别!
如何解决幻读
**MVCC(多版本并发控制):**在高性能MySQL第三版中可重复读隔离级别的描述中写到:可重复读不能避免幻读的产生。幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新行,当之前的事务再次读取该范围的记录时,会产生幻行。InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读问题。
我们先来看一个可重复读隔离级别(RR)下的实例:
| 事务/时刻 | 事务A | 事务B |
|---|---|---|
| t1 | begin; | |
| t2 | select * from student | begin; |
| t3 | insert into student(…) | |
| t4 | select * from student |
在t4时刻,理论上是不是和t2的查询结果不一致呢,如果是,那就还会产生幻读;
事实上,不会,这是MVCC的功劳。
MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,在某个时间点事务开启时,其看到的数据是该时间点之前已经提交的数据的快照内容,这就保证了事务执行期间看到的数据时一致的。
版权声明:本文标题:MySQL是如何解决幻读问题 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1754941381a3052610.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论