君哥聊技术

面试官:什么是快照读?什么是当前读?有什么区别?

大家好,我是君哥。

使用 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 whereid=10;

在可重复读隔离级别下,读取到的数据如下:

Image

在读已提交隔离级别下,读取到的数据如下图:Image

总结,快照读的特点就是读取视图数据,不加锁,非阻塞,执行 SQL 语句一般是简单查询:

SELECT xxx FROMtableWHERE 条件

2.当前读

跟快照读对应的就是当前读,特点是读取数据最新提交的版本,在读取时会对数据进行加锁,以防止其他事务并发修改这条数据。优点是强一致,可以读取到数据最新版本,防止丢失更新。缺点是有加锁带来的阻塞和性能损耗。

当前读涉及的 SQL 如下:

SELECT xxx FROMTABLELOCKINSHAREMODE (共享锁);

SELECT xxx FROMTABLEFORUPDATE (排它锁)

UPDATETABLEset xxx (更新前先加排它锁)

DELETEFROMTABLEWHERE xxx (删除前先加排它锁)

INSERTINTOTABLE xxx (加排它锁)

3.总结

当前读和快照读的区别总结如下:

差异点
快照读
当前读
数据版本
基于快照,不一定最新
最新提交版本
是否加锁
不加
加锁
一致性
可能有不一致情况
强一致
并发性
强
可能有阻塞
实现原理
MVCC
数据库锁
适用隔离级别
可重复读、读已提交
全部

对于简单的数据查询,不要求查询最新提交数据,可以考虑使用快照读。如果要求读取到最新提交数据,那就考虑使用当前读。

往期精彩:
又老性能又差,为什么好多公司依然选择 RabbitMQ?

45 个知识点,带你入门消息队列!

引入了 Disruptor 后,系统性能大幅提升!

阿里二面:聊聊 MySQL 主从同步方案的优缺点

面试官:MySQL双主架构有什么优缺点?

面试官:使用 MySQL 时你遇到过哪些索引失效的场景

面试官:MySQL表中有2千万条数据,B+树层高是多少?

面试官:MySQL JOIN 表太多,你有哪些优化思路?

感谢阅读,如果对你有帮助,请点赞和在看。欢迎加我微信:zhujinjun86。

号内回复 seata,下载《阿里分布式中间件Seata从入门到精通》

号内回复 beijing,下载我总结的北京上百家知名科技公司

号内回复 aqs,下载《40张图精通Java AQS》