“读取倾斜”与“不可重复读取”(事务)

5 database transactions isolation-level non-repeatable-read

我阅读了下面的《初学者\xe2\x80\x99s读写倾斜现象指南》《初学者\xe2\x80\x99s不可重复读异常指南》来了解什么是读倾斜不可重复读

\n

读取倾斜

\n

在此输入图像描述

\n

不可重复读取

\n

在此输入图像描述

\n

但是,我无法区分读取倾斜不可重复读取,基本上,似乎两者都可以通过REPEATABLE READ隔离SERIALIZABLE级别来防止来防止。

\n

我的问题:

\n
    \n
  1. 读取倾斜不可重复读取有什么区别\n读取

    \n
  2. \n
  3. 可以通过或来防止读取倾斜不可重复读取REPEATABLE READSERIALIZABLE吗?

    \n
  4. \n
\n

小智 4

  • 不可重复读(模糊读)是指一个事务至少读取同一行两次,但第一次和第二次读取同一行的数据不同,因为其他事务同时(并发)更新同一行的数据并提交。*我在不可重复读取和幻读之间有什么区别?中解释了有关不可重复读取的更多信息。

  • 读倾斜是指在两个不同的查询中,一个事务读取到不一致的数据,因为在第一个和第二个查询之间,其他事务插入、更新或删除数据并提交。最后,不一致的数据会产生不一致的结果。

下面有一些读取倾斜的示例,您可以使用MySQL2 个命令提示符来执行这些操作。

对于下面这些读取倾斜的示例,您需要设置READ COMMITTED隔离级别以发生读取倾斜

SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
Run Code Online (Sandbox Code Playgroud)

并且,有一个带有、和的bank_account表格,如下所示。idnamebalance

bank_account桌子:

ID 姓名 平衡
1 约翰 600
2 汤姆 400

下面的这些步骤显示了读取偏差。*300从约翰的余额转移到汤姆的余额。然后,T1 从 Tom 的余额中读取100(Inconsistent data)而不是400。最后,600+ 100=700(Inconsistent result)约翰和汤姆的余额总计:

流动 交易1(T1) 交易2(T2) 解释
步骤1 BEGIN; T1开始。
第2步 BEGIN; T2开始。
步骤3 SELECT balance FROM bank_account WHERE id = 1;

600
T1 读取600
步骤4 UPDATE bank_account set balance = 900 WHERE id = 1; T2 更新600900因为300是从 Tom 的余额转入的。
步骤5 UPDATE bank_account set balance = 100 WHERE id = 2; T2 更新400100因为300已转入 John 的余额。
步骤6 COMMIT; T2 提交。
步骤7 SELECT balance FROM bank_account WHERE id = 2;

100
T1 读取100(Inconsistent data)而不是400T2 提交之后。
步骤8 600 + 100 = 700 最后,T1700(Inconsistent result)代替1000

*发生读取倾斜。

步骤9 COMMIT; T1 提交。

下面的这些步骤还显示了读取偏差。*300从汤姆的余额中提取。然后,T1 读取100(Inconsistent data)而不是400. 最后,600+ 100=700(Inconsistent result)约翰和汤姆的余额总计:

流动 交易1(T1) 交易2(T2) 解释
步骤1 BEGIN; T1开始。
第2步 BEGIN; T2开始。
步骤3 SELECT balance FROM bank_account WHERE id = 1;

600
T1 读取600
步骤4 UPDATE bank_account set balance = 100 WHERE id = 2; T2 更新400100因为300从 Tom 的余额中提取。
步骤5 COMMIT; T2 提交。
步骤6 SELECT balance FROM bank_account WHERE id = 2;

100
T1 读取100(Inconsistent data)而不是400T2 提交之后。
步骤7 600 + 100 = 700 最后,T1700(Inconsistent result)代替1000

*发生读取倾斜。

步骤8 COMMIT; T1 提交。

另外,这也是read skew的例子。有teacher和 的student表格id如下name所示。

teacher桌子:

ID 姓名
1 约翰
2 汤姆

student桌子:

ID 姓名
1 安娜
2 莎拉
3 大卫
4 标记
5

下面的这些步骤显示了读取偏差。* LisaPeterRoy插入到“student”表中。然后,T1 读取8(Inconsistent data)而不是5. 最后,2+ 8=9(Inconsistent result)教师和学生总数:

流动 交易1(T1) 交易2(T2) 解释
步骤1 BEGIN; T1开始。
第2步 BEGIN; T2开始。
步骤3 SELECT count(*) FROM teacher;

2
T1 读取2
步骤4 INSERT INTO student values (6, 'Lisa'), (7, 'Peter'), (8, 'Roy'); T2 插入物LisaPeterRoy
步骤5 COMMIT; T2 提交。
步骤6 SELECT count(*) FROM student;

8
T1 读取8(Inconsistent data)而不是5T2 提交之后。
步骤7 2 + 8 = 10 最后,T110(Inconsistent result)代替7

*出现读取倾斜!!

步骤8 COMMIT; T1 提交。

下表是我在MySQLPostgreSQL中每个隔离级别的读取偏差的实验结果。*表示发生,表示不发生YesNo

MySQL

隔离级别 读取倾斜
未提交的阅读 是的
已提交读 是的
可重复读取
可串行化

PostgreSQL

隔离级别 读取倾斜
未提交的阅读 是的
已提交读 是的
可重复读取
可串行化