目录

并发读取数据出现的问题

脏读:一个事务读取另一个事务未提交的数据

幻读:一个事务内进行了多次读取,数据总量不一致

不可重复读:一个事务对同一数据进行读取,前后数据内容不一致

区别:

隔离级别

读未提交:所有读问题都有可能发生,一般不会采取这种隔离级别

读已提交:只能避免脏读发生,Oracle默认的隔离级别

可重复读:能够避免脏读、不可重复读,MySQL中Innodb引擎默认的隔离级别

可串行化:可以解决所有读问题,但是由于是串行执行,效能效率比较低

并发事务下发生的问题与解决方式

这张图有点问题,MySQL 的 RR 级别应该是允许幻读的,和 ANSI SQL 一致。只是 innodb 通过 gap lock 避免了幻读。

这张图有点问题,MySQL 的 RR 级别应该是允许幻读的,和 ANSI SQL 一致。只是 innodb 通过 gap lock 避免了幻读。

并发读取数据出现的问题

<aside> 💡 幻读、脏读、不可重复读统称为 serialization anomaly

</aside>

脏读:一个事务读取另一个事务未提交的数据

A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个时候A事务立即读取了这个脏数据,但事务B良心发现,又用回滚把数据恢复成原来干净、纯粹的样子,而事务A却什么都不知道,最终结果就是事务A读取了此次的脏数据,称为脏读

幻读(phantom read):一个事务内进行了多次读取,数据总量不一致

事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,就像产生了幻觉一样,平白无故的多了几条数据,成为幻读。

<aside> 💡 从 ANSI SQL 标准来说,Repeatable Read 允许幻读。

但是现实中 DBMS 普遍在实现 RR 的时候避免了幻读,比如 MySQL 的 RR 允许幻读,但是 InnoDB 的 RR 通过 gap lock 避免了幻读。在 DBMS 领域,为了对标 ANSI SQL 的真 RR,又发明了 Read Stability

幻读和不可重复读的区别在于,不可重复读读取的是同一个数据,而幻读是读取的不同的数据,只是这些数据作为一个整体的完整性被破坏了。

使用一致性快照可以解决幻读。

‣ - P84

</aside>