MySQL如何使用MVCC解决脏读、不可重复读和幻读问题

后端 潘老师 5个月前 (11-21) 140 ℃ (0) 扫码查看

本文主要讲解MySQL如何使用MVCC解决脏读、不可重复读和幻读问题相关内容,我们一起来学习下!

并发情况下,读操作可能存在脏读、不可重复读和幻读的问题。可以通过MVCC(Multi-Version Concurrency Control, 多版本并发控制)机制解决这些问题。

一、什么是脏读(Dirty Read)

一个事务读取了已被另一个事务修改,但尚未提交的数据(脏数据)。

二、什么是不可重复读(Nonrepeate Read)

在同一个事务中,同一个查询在时刻1读取某一行,在时刻2重读取这一行数据的时候,发现这一行的数据已经发生修改,可能被更新了,也可能被删除了。

三、什么是幻读(Phantom Read)

在同一事务中,当同一查询多次执行的时候,由于其他插入操作的事务提交,会导致每次返回不同的结果集。

SQL标准定义了四个隔离级别:

隔离级别 描述 脏读 不可重复读 幻读
Read Uncommitted 读未提交 所有事务都可以看到其他未提交事务的执行结果,事务中的修改,即使没有提交,对其他事务也是可见的。 可能 可能 可能
Read Committed 读已提交 一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。 不可能 可能 可能
Repeatable Read 可重复读 同一个事务,在多次读取同一行数据的时候,得到的是同样的结果。 不可能 不可能 可能
Serializable 可串行化 强制事务排序,强制事务串行执行,使之不可能相互冲突。 不可能 不可能 不可能

InnoDB存储引擎默认的隔离级别是可重复读。

-- 查询当前会话的事务隔离级别
SELECT @@transaction_isolation;

-- 查询系统的事务隔离级别
SELECT @@global.transaction_isolation;
mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)

mysql> SELECT @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ                |
+--------------------------------+
1 row in set (0.00 sec)

接下来看一下MVCC是如何解决脏读、不可重复读、幻读的问题的。MVCC多版本并发控制,能够实现在同一时刻,不同事务中读取到的数据是不同的(即多版本)。

MVCC通过隐藏列和undo log实现ReadView,通过ReadView来判断不同事务要使用哪个版本的数据。

一、如何解决脏读问题

事务A在查询余额前会生成ReadView,事务B此时还未提交,对数据的修改对ReadView不可见,所以事务A中读取到的是修改前的数据。

二、如何解决不可重复读问题

事务A在第1次查询余额前会生成ReadView,事务B的修改对ReadView是不可见的,再次查询时通过判断事务B已经提交的修改对事务A仍然是不可见的,就通过undo log查询修改前的版本的数据。

三、如何解决幻读问题

解决幻读的问题和解决不可重复读的问题类似。

使用MVCC避免脏读、不可重复读、幻读,保证了隔离性,MVCC中使用的是非加锁读,也称作快照读。

另外还可以使用加锁读:

START TRANSACTION;
-- 共享锁读取
SELECT * FROM users WHERE id=1 LOCK IN SHARE MODE;

-- 排他锁读取
SELECT * FROM users WHERE id=1 FOR UPDATE;

UPDATE users SET name="王小明" WHERE id=1;
COMMIT;

SELECT ... LOCK IN SHARE MODE;用于在查询数据时获取共享锁,防止其他事务对数据进行写操作,但允许事务对数据进行读操作。

SELECT ... FOR UPDATE;用于在查询数据时获取排他锁,防止其他事务对数据进行读写操作。

总结

以上就是MySQL如何使用MVCC解决脏读、不可重复读和幻读问题的全部内容,希望对你有帮助,欢迎持续关注潘子夜个人博客(www.panziye.com),学习愉快哦!


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/11688.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】