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可以通过或来防止读取倾斜和不可重复读取REPEATABLE READSERIALIZABLE吗?
小智 4
不可重复读(模糊读)是指一个事务至少读取同一行两次,但第一次和第二次读取同一行的数据不同,因为其他事务同时(并发)更新同一行的数据并提交。*我在不可重复读取和幻读之间有什么区别?中解释了有关不可重复读取的更多信息。
读倾斜是指在两个不同的查询中,一个事务读取到不一致的数据,因为在第一个和第二个查询之间,其他事务插入、更新或删除数据并提交。最后,不一致的数据会产生不一致的结果。
下面有一些读取倾斜的示例,您可以使用MySQL和2 个命令提示符来执行这些操作。
对于下面这些读取倾斜的示例,您需要设置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 更新600为900因为300是从 Tom 的余额转入的。 |
|
| 步骤5 | UPDATE bank_account set balance = 100 WHERE id = 2; |
T2 更新400为100因为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 更新400为100因为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 | 凯 |
下面的这些步骤显示了读取偏差。* Lisa,Peter并Roy插入到“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 插入物Lisa,Peter和Roy。 |
|
| 步骤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 提交。 |
下表是我在MySQL和PostgreSQL中每个隔离级别的读取偏差的实验结果。*表示发生,表示不发生。YesNo
MySQL:
| 隔离级别 | 读取倾斜 |
|---|---|
| 未提交的阅读 | 是的 |
| 已提交读 | 是的 |
| 可重复读取 | 不 |
| 可串行化 | 不 |
PostgreSQL:
| 隔离级别 | 读取倾斜 |
|---|---|
| 未提交的阅读 | 是的 |
| 已提交读 | 是的 |
| 可重复读取 | 不 |
| 可串行化 | 不 |
| 归档时间: |
|
| 查看次数: |
2175 次 |
| 最近记录: |