面试官:什么是快照读?什么是当前读?有什么区别?
大家好,我是君哥。
使用 MySQL 时,我们经常会听到快照读、当前读这样的概念,今天我们就来聊一聊快照读、当前读。
快照读和当前读,主要区别在于是否读取到最新提交的数据,是否需要加锁,它们对数据库的并发性能有所不同。
1.快照读
快照读,读取的是数据的快照,通过读视图,提供非阻塞读取,代替加锁机制,提高并发性能。
我们知道,MySQL 事务隔离级别有 4 个:
串行化(Serializable):事务对数据读写都是串行化的。可重复读(Repeatable Read):事务执行过程中,多次读取同一行数据,读取结果一致。MySQL 默认隔离级别就是可重复读。读已提交数据(Read Committed):事务执行过程中,如果有其他事务修改了数据并且提交事务,当前事务可以读取到最新提交的数据。读未提交数据(Read Uncommitted):事务执行过程中,可以读取到其他事务未提交的数据。其中可重复读和读已提交数据,依托 MVCC(多版本并发控制)实现了快照读。
不同的是,可重复读是在事务开始时创建视图,每个事务就使用一个快照,所以多次读取结果是一样的,看不到新提交的数据。而读已提交是在每次语句执行前创建新的视图,所以能读取到新提交的数据。
比如有一张表 t_acct,其中有 id,account、amount 三个字段,在一个事务中有一条 SQL 语句被执行了 3 次:
复制
select amount from t_acct where id=10;1.
在可重复读隔离级别下,读取到的数据如下:
图片
在读已提交隔离级别下,读取到的数据如下图:
图片
总结,快照读的特点就是读取视图数据,不加锁,非阻塞,执行 SQL 语句一般是简单查询:
复制
SELECT xxx FROM table WHERE 条件1.
2.当前读
跟快照读对应的就是当前读,特点是读取数据最新提交的版本,在读取时会对数据进行加锁,以防止其他事务并发修改这条数据。优点是强一致,可以读取到数据最新版本,防止丢失更新。缺点是有加锁带来的阻塞和性能损耗。
当前读涉及的 SQL 如下:
复制
SELECT xxx FROMTABLELOCKINSHAREMODE (共享锁);
SELECT xxx FROMTABLEFORUPDATE (排它锁)
UPDATETABLEset xxx (更新前先加排它锁)
DELETEFROMTABLEWHERE xxx (删除前先加排它锁)
INSERTINTOTABLE xxx (加排它锁)1.2.3.4.5.6.7.8.9.
3.总结
当前读和快照读的区别总结如下:
差异点
快照读
当前读
数据版本
基于快照,不一定最新
最新提交版本
是否加锁
不加
加锁
一致性
可能有不一致情况
强一致
并发性
强
可能有阻塞
实现原理
MVCC
数据库锁
适用隔离级别
可重复读、读已提交
全部
对于简单的数据查询,不要求查询最新提交数据,可以考虑使用快照读。如果要求读取到最新提交数据,那就考虑使用当前读。
阅读剩余
THE END