Merge pull request #273 from Sdot-Python/master

[docs] ch7 术语统一,写入偏斜->写入偏差,写偏差->写入偏差
This commit is contained in:
YIN, Gang 2022-10-29 10:22:29 +08:00 committed by GitHub
commit c7a97457da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

16
ch7.md
View File

@ -462,7 +462,7 @@ UPDATE wiki_pages SET content = '新内容'
另一方面最后写入胜利LWW的冲突解决方法很容易丢失更新如 “[最后写入胜利(丢弃并发写入)](ch5.md#最后写入胜利(丢弃并发写入))” 中所述。不幸的是LWW 是许多复制数据库中的默认方案。
### 写入偏与幻读
### 写入偏与幻读
前面的章节中,我们看到了 **脏写****丢失更新**,当不同的事务并发地尝试写入相同的对象时,会出现这两种竞争条件。为了避免数据损坏,这些竞争条件需要被阻止 —— 既可以由数据库自动执行,也可以通过锁和原子写操作这类手动安全措施来防止。
@ -478,13 +478,13 @@ UPDATE wiki_pages SET content = '新内容'
在两个事务中,应用首先检查是否有两个或以上的医生正在值班;如果是的话,它就假定一名医生可以安全地休班。由于数据库使用快照隔离,两次检查都返回 2 所以两个事务都进入下一个阶段。Alice 更新自己的记录休班了,而 Bob 也做了一样的事情。两个事务都成功提交了,现在没有医生值班了。违反了至少有一名医生在值班的要求。
#### 写偏差的特征
#### 写偏差的特征
这种异常称为 **写偏差**【28】。它既不是 **脏写**,也不是 **丢失更新**因为这两个事务正在更新两个不同的对象Alice 和 Bob 各自的待命记录)。在这里发生的冲突并不是那么明显,但是这显然是一个竞争条件:如果两个事务一个接一个地运行,那么第二个医生就不能歇班了。异常行为只有在事务并发进行时才有可能发生。
这种异常称为 **写偏差**【28】。它既不是 **脏写**,也不是 **丢失更新**因为这两个事务正在更新两个不同的对象Alice 和 Bob 各自的待命记录)。在这里发生的冲突并不是那么明显,但是这显然是一个竞争条件:如果两个事务一个接一个地运行,那么第二个医生就不能歇班了。异常行为只有在事务并发进行时才有可能发生。
可以将写入偏差视为丢失更新问题的一般化。如果两个事务读取相同的对象,然后更新其中一些对象(不同的事务可能更新不同的对象),则可能发生写入偏差。在多个事务更新同一个对象的特殊情况下,就会发生脏写或丢失更新(取决于时序)。
我们已经看到,有各种不同的方法来防止丢失的更新。但对于写偏差,我们的选择更受限制:
我们已经看到,有各种不同的方法来防止丢失的更新。但对于写偏差,我们的选择更受限制:
* 由于涉及多个对象,单对象的原子操作不起作用。
* 不幸的是,在一些快照隔离的实现中,自动检测丢失更新对此并没有帮助。在 PostgreSQL 的可重复读MySQL/InnoDB 的可重复读Oracle 可串行化或 SQL Server 的快照隔离级别中都不会自动检测写入偏差【23】。自动防止写入偏差需要真正的可串行化隔离请参阅 “[可串行化](#可串行化)”)。
@ -507,9 +507,9 @@ COMMIT;
* 和以前一样,`FOR UPDATE` 告诉数据库锁定返回的所有行以用于更新。
#### 写偏差的更多例子
#### 写偏差的更多例子
写偏差乍看像是一个深奥的问题,但一旦意识到这一点,很容易会注意到它可能发生在更多场景下。以下是一些例子:
偏差乍看像是一个深奥的问题,但一旦意识到这一点,很容易会注意到它可能发生在更多场景下。以下是一些例子:
* 会议室预订系统
@ -771,7 +771,7 @@ WHERE room_id = 123 AND
#### 基于过时前提的决策
先前讨论了快照隔离中的写入偏差(请参阅 “[写入偏斜与幻读](#写入偏斜与幻读)”)时,我们观察到一个循环模式:事务从数据库读取一些数据,检查查询的结果,并根据它看到的结果决定采取一些操作(写入数据库)。但是,在快照隔离的情况下,原始查询的结果在事务提交时可能不再是最新的,因为数据可能在同一时间被修改。
先前讨论了快照隔离中的写入偏差(请参阅 “[写入偏差与幻读](#写入偏差与幻读)”)时,我们观察到一个循环模式:事务从数据库读取一些数据,检查查询的结果,并根据它看到的结果决定采取一些操作(写入数据库)。但是,在快照隔离的情况下,原始查询的结果在事务提交时可能不再是最新的,因为数据可能在同一时间被修改。
换句话说,事务基于一个 **前提premise** 采取行动(事务开始时候的事实,例如:“目前有两名医生正在值班”)。之后当事务要提交时,原始数据可能已经改变 —— 前提可能不再成立。
@ -849,7 +849,7 @@ WHERE room_id = 123 AND
两个客户端同时执行 **读取 - 修改 - 写入序列**。其中一个写操作,在没有合并另一个写入变更情况下,直接覆盖了另一个写操作的结果。所以导致数据丢失。快照隔离的一些实现可以自动防止这种异常,而另一些实现则需要手动锁定(`SELECT FOR UPDATE`)。
* 写偏差
* 写偏差
一个事务读取一些东西,根据它所看到的值作出决定,并将该决定写入数据库。但是,写入时,该决定的前提不再是真实的。只有可串行化的隔离才能防止这种异常。