今天看啥  ›  专栏  ›  Colors

大白话讲解脏写、脏读、可重复读和幻读

Colors  · 掘金  ·  · 2021-04-24 09:50
阅读 17

大白话讲解脏写、脏读、可重复读和幻读

前言

当多个事务并发执行的时候,会导致什么问题?

我们知道,执行sql是在buffer pool中对数据进行查询或者修改。如若多个事务同时更新一行数据会出现什么问题?

1. 脏写

当事务A和事务B同时去更新同一行数据时,事务A先更新,事务B后更新。

图 1-1

那么此时,undo log就会记录了事务A所改数据的旧值,假设旧值为 null。随后事务B也对该行数据进行了更新,覆盖掉A更新的值。此时事务A突然发生回滚,那么就会根据它的undo log进行回滚。

事务A进行了回滚,那么该数据的值就变成了更新前的null值。

图1-2

然而,事务B并不知道此事,发现自己更新的值没有了。这就是 脏写

本质上,就是一个事务修改了另外一个没提交的事务的值(没提交有可能回滚),而导致有可能数据前后不一致的问题。

2. 脏读

同样有事务A和事务B。事务A去更新了一行数据,事务B刚好查询到了该行数据,此时事务B拿到的值为A更新的值。

图 2-1

事务B拿到值后便去业务系统进行各种业务逻辑处理等等,这时,事务A突然回滚了,又把undo log的值回滚到该行数据。紧接着事务B再次查询该行数据的时候,发现前后的值不一样。这就是脏读

图 2-2

本质上,就是一个事务查询到了另个一个未提交的事务的值,而导致有可能数据前后不一致的问题。

3. 不可重复读

在避免脏读的前提下,还有可能出现的不可重复读

这类情况是在什么场景下发生的呢?

假设,有一个前提,事务B在更新某行数据,但暂未提交,在未提交事务的时间里,事务A是读不到该行数据的。必须等事务B提交了,事务A才能读取到它修改的值。这样就可以避免脏读。

这时,假设事务A第一次查询到的值为A值。

图 3-1

事务B把该行数据的值改为B值并立即提交事务。而事务A尚未提交事务,在事务执行期间进行第二次查询,所以事务A第二次查询到的值为B值。

图 3-2

紧接着事务C再次更新数据为C值,并提交了事务。此时,事务A在未提交事务的情况下,进行第三次查询,查到的值为C。

图 3-3

不可重复读就是以上这种情况,事务A未提交事务,每次读到的数据可能都不一样。

通过以上分析,那可重复读,就很好理解了。即希望,事务A每次读到的值都是A值。

4. 幻读

假设事务A需要多次批量查询数据,第一次查询到了十条数据

图 4-1

此时事务B往表里插入了几条数据,且B提交了事务,那么此时,就会多出几行数据

图 4-2

接着事务A再次进行查询时,由于事务B的提交,导致事务A查询多出来了几条数据

图 4-3

这样就出现了和查询第一次没见到的数据,就是幻读

本质上,就是一个事务用一样的sql进行多次查询,每次查询到没见过的数据。




原文地址:访问原文地址
快照地址: 访问文章快照