1.1 简介
现在乐趣开始了——交易如何运作的理论。当您在不同线程中更改相同数据时,如何保持系统正常工作?或者您想在另一笔交易中执行一笔交易?我们将开始通过研究事务的隔离性来寻找这些问题的答案……
事务隔离级别是一个条件值,它决定了由于 DBMS 中逻辑并行事务的执行,允许不一致数据的程度。事务隔离级别的规模包含许多值,从低到高排列;更高的隔离级别对应于更好的数据一致性,但它的使用可能会减少物理上并行事务的数量。
相反,较低的隔离级别允许更多并行事务,但会降低数据准确性。因此,选择所使用的事务隔离级别,信息系统的开发人员在一定程度上提供了工作速度和确保从系统接收的数据的保证一致性之间的选择。
使用事务并发访问的问题
当事务并行执行时,可能会出现以下问题:
- 丢失更新——如果一个数据块被不同的事务同时更改,则所有更改都将丢失,除了最后一个;
- “脏”读(eng. Dirty read) ——读取交易添加或更改的数据,随后不会被确认(回滚);
- 不可重复读(eng. non-repeatable read) ——当在同一个事务内重新读取时,之前读取的数据被改变;
- 幻读- 一个事务在其执行期间多次根据相同的标准选择许多行。在这些获取之间的另一个事务添加行或修改第一个事务的获取条件中使用的某些行的列并成功结束。结果,第一个事务中的相同选择会给出不同的行集。
考虑可能发生这些问题的情况。
1.2 丢失更新
当一个数据块被不同的事务同时更改时,其中一个更改丢失的情况。
假设有两个事务同时运行:
事务 1 | 交易 2 |
---|---|
更新 tbl1 SET f2=f2+20 WHERE f1=1; | 更新 tbl1 SET f2=f2+25 WHERE f1=1; |
在这两个事务中,f2 字段的值都发生了变化;完成后,该字段的值必须增加 45。实际上,可能会发生以下一系列操作:
- 两个事务同时读取字段的当前状态。这里不需要精确的物理并发,在另一个事务写入其结果之前按顺序完成第二次读取操作就足够了。
- 两个事务都通过分别将先前读取的值加上 20 和 25 来计算新的字段值。
- 事务尝试将计算结果写回字段 f2。由于物理上不可能同时执行两次写操作,因此实际上其中一个写操作会先执行,另一个会晚执行。第二次写操作将覆盖第一次的结果。
这样一来,f2字段的值,在两笔交易完成后,可能不会增加45,而是增加20或25,也就是说,其中一笔数据更改交易将“消失”。
1.3 “脏”读
读取由稍后将无法提交(回滚)的事务添加或修改的数据。
假设我们有两个事务由执行以下 SQL 语句的不同应用程序打开:
事务 1 | 交易 2 |
---|---|
更新 tbl1 SET f2=f2+1 WHERE f1=1; | |
从 tbl1 中选择 f2,其中 f1=1; | |
回滚工作; |
在事务1中,改变了字段f2的值,然后在事务2中,选择了这个字段的值。之后事务1被回滚,结果第二个事务接收到的值会和数据库中存储的值不一样。
1.4 不可重复读
当在同一事务中重新读取时,先前读取的数据被更改的情况。
假设我们有两个事务由执行以下 SQL 语句的不同应用程序打开:
事务 1 | 交易 2 |
---|---|
从 tbl1 中选择 f2,其中 f1=1; | |
更新 tbl1 SET f2=f2+3 WHERE f1=1; | |
犯罪; | |
从 tbl1 中选择 f2,其中 f1=1; |
在事务2中,选择了字段f2的值,然后在事务1中,更改了字段f2的值。如果再次尝试从事务 2 中的字段 f2 中选择一个值,将得到不同的结果。当为了部分修改数据并将其写回数据库而读取数据时,这种情况尤其不能接受。
1.5 阅读“幻影”
在同一事务中重复读取期间,同一选择给出不同行集的情况。
假设有两个事务被不同的应用打开,执行如下SQL语句:
事务 1 | 交易 2 |
---|---|
从 tbl1 中选择总和 (f2); | |
插入 tbl1 (f1,f2) 值 (15,20); | |
犯罪; | |
从 tbl1 中选择总和 (f2); |
事务2执行一条SQL语句,使用了字段f2的所有值。然后在事务1中插入了一个新行,导致事务2中的SQL语句重新执行产生了不同的结果。这种情况称为幻读(phantom reading)。它与不可重复读取的不同之处在于,重复数据访问的结果发生变化不是由于数据本身的更改/删除,而是由于新(幻像)数据的出现。
GO TO FULL VERSION