隔离级别
当应用程序访问数据时, 隔离级别决定了该数据被锁定或与其他并发进程隔离的程度。 隔离级别在单位工作时间内有效。
- 应用程序读取或更新的行可供其他同时运行的应用程序进程使用的程度。
- 其他同时运行的应用程序进程的更新活动对应用程序的影响程度。
静态 SQL 语句的隔离级别是作为程序包的属性指定的,并且将应用于使用该程序包的应用程序进程。 要指定隔离级别,请在程序准备过程中设置
ISOLATION 绑定或预编译选项。 对于动态 SQL 语句,默认隔离级别是在准备语句时为包指定的隔离级别。 请使用
SET CURRENT ISOLATION 语句对会话中发出的动态 SQL 语句指定另一隔离级别。 有关更多信息,请参阅 CURRENT ISOLATION 专用寄存器
。 对于静态 SQL 语句和动态 SQL 语句而言,select-statement
中的 isolation-clause
都将覆盖专用寄存器(如果已设置的话)和绑定选项值。 有关更多信息,请参阅 Select-statement
。
隔离级别由锁定实施,所使用的锁定的类型将限制或阻止并发应用程序进程访问数据。 已声明临时表以及它们的行无法被锁定,这是因为它们仅可供声明它们的应用程序访问。
- 共享 (S)
- 挂起 S 锁定之后,并发应用程序进程只能对数据执行只读操作。
- 更新 (U)
- 在U锁下,如果并发应用程序未声明可能会更新某一行,则这些应用程序仅限于对数据进行只读操作。 数据库管理器假定当前正在查看行的进程可能会更新该行。
- 互斥 (X)
- 挂起 X 锁定之后,并发应用程序进程将无法以任何方式访问数据。 这种锁类型不适用于隔离级别为未承诺读取(UR)的应用程序,这种应用程序可以读取但不能修改数据。
以下按性能影响递减、数据访问或更新时所需维护递增的顺序,详细描述了各个隔离级别。
可重复的读 (RR)
可重复的读隔离级别将锁定应用程序在工作单元 (UOW) 运行期间引用的所有行。 如果应用程序在同一个工作单元中发出 SELECT 语句两次,那么每次将返回相同的结果。 在RR下,丢失更新、访问未提交的数据、不可重复读取和幻影读取是不可能的。
在 RR 隔离级别下,应用程序在 UOW 完成前可以任意次地检索和处理行。 但是,在该 UOW 完成之前,其他应用程序均无法更新、删除或插入将会影响结果集的行。 在 RR 隔离级别下运行的应用程序无法看到其他应用程序所作的未落实更改。 这种隔离级别可确保所有返回的数据在应用程序看到数据之前保持不变,即使使用了临时表或行阻止。
所引用的每一行都将被锁定,而不仅仅是锁定所检索的行。 例如,如果扫描 10000 行并对它们应用谓词,尽管可能只有 10 行满足条件,但仍会锁定全部的 10000 行。 如果再次运行查询,另一个应用程序无法插入或更新查询引用的行列表中的行。 RR的这一特性可防止误读。
由于 RR 可以获取大量锁,因此数量可能会超过 locklist 和 maxlocks 数据库配置参数指定的限制。 为了避免锁升级,如果锁升级的可能性较大,优化程序可能会选择为索引扫描获取单个表级锁。 如果您不希望进行表级别锁定,那么请使用“读稳定性”隔离级别。
当 Db2评估参照约束时,可能会偶尔将外部表扫描时使用的隔离级别升级到RR。 无论用户之前设置的隔离级别如何,升级都可能发生。 由于隔离级别升级,提交前可能会有更多锁被保持,这增加了死锁或锁超时的可能性。 为了避免这些问题,请创建只包含外键列的索引以供引用完整性扫描使用。
读稳定性 (RS)
读稳定性隔离级别只锁定应用程序在工作单元运行期间检索的那些行。 RS确保在UOW期间读取的任何合格行在UOW完成之前不会被其他应用程序进程更改。 RS还确保,在另一个应用程序进程提交更改之前,无法读取该进程对某行的任何更改。 在RS模式下,无法访问未提交的数据和不可重复的读取。 但是,有可能进行幻像读。 对行进行的并行更新还可能引入幻像读,在幻像读中,旧值不满足原始应用程序的搜索条件,但新更新值满足。
- 应用程序进程 P1 读取满足某个搜索条件的行集 n。
- 然后应用程序进程 P2 插入满足该搜索条件的一行或多行并落实这些新插入操作。
- P1 再次读取具有相同搜索条件的行集,并获取原始行和 P2。
在 Db2 pureScale® 环境中,如果行在不同成员上同时更新,则在此隔离级别运行的应用程序可能会拒绝先前提交的行值。 要覆盖此行为,请指定 WAIT_FOR_OUTCOME 选项。
这种隔离级别可确保所有返回的数据在应用程序看到数据之前保持不变,即使使用了临时表或行阻止。
RS 隔离级别既提供了高度的并行性,也提供了稳定的数据视图。 所以,优化器确保在发生锁定升级前不获取表级别锁定。
- 在并发环境中运行。
- 要求合格行在一个工作单元内保持稳定。
- 在一个工作单元内,不会重复发出相同的查询。
- 当在一个工作单元内多次发出查询时,不需要相同的查询结果集。
游标稳定性 (CS)
游标稳定性隔离级别可在事务处理期间锁定游标所在的任何行。 此锁在取下下一排或交易结束前一直有效。 但是,如果更改了该行中的任何数据,那么在落实更改之前将一直挂起该锁定。
在此隔离级别下,其他应用程序无法在可更新游标定位于某一行上时更新或删除该行。 在 CS 下,无法访问其他应用程序未落实的数据。 然而,不可重复读取和幻影读取是可能的。
CS 是缺省隔离级别。 如果您希望最大程度地提高并行性,并且只需要查看已落实的数据时,此隔离级别适用。 在此隔离级别下运行的扫描将根据配置参数 cur_commit (当前承诺)进行。
在 Db2 pureScale 环境中,如果在另一个成员上同时更新该行,则在此隔离级别运行的应用程序可能会返回或拒绝先前提交的行值。 并行访问权解析设置的 WAIT FOR OUTCOME 选项可用于覆盖此行为。
未落实的读 (UR)
未落实的读隔离级别允许应用程序访问其他事务未落实的更改。 并且,UR 不会阻止其他应用程序访问正被读取的行,除非该应用程序尝试更改或删除表。
- 您对只读表进行查询。
- 您只发出SELECT语句,查看其他应用程序提交的数据没有问题。
- 只读游标可访问其他事务未落实的大部分更改。
- 在事务处理期间,正由其他事务创建或删除的表、视图和索引不可用。 其他事务进行的任何其他更改在落实或回滚前都可被读取。 在UR下运行的可更新游标,其隔离级别与CS相同。
- 将该应用程序中的游标修改为明确游标。 将 SELECT 语句更改为包括 FOR READ ONLY 子句。
- 将光标保留在应用程序中,使其保持模糊状态。 但是,请预先编译程序,或者将其与“阻止所有”和“静态读取”选项绑定,以便在程序运行时将模糊光标视为只读。
隔离级别 UR在列式表和行式表中的行为可能有所不同。
隔离级别的比较
| UR | CS | RS | RR | |
|---|---|---|---|---|
| 应用程序能否看到其他应用程序进程所做的未提交更改? | 是 | False | False | False |
| 应用程序更新能否修改其他应用程序进程所做的更改? | False | False | False | False |
| 重新运行语句是否受其他应用程序进程的影响? 1 | 是 | 是 | 是 | 否2 |
| 已更新的行是否能够被其他应用程序进程更新? 3 | False | False | False | False |
| 已更新的行是否能够被其他在除 UR 以外的隔离级别下运行的应用程序进程读取? | False | False | False | False |
| 已更新的行是否能够被其他在 UR 隔离级别下运行的应用程序进程读取? | 是 | 是 | 是 | 是 |
| 已访问的行是否能够被其他应用程序进程更新? 4 | 是 | 是 | False | False |
| 已访问的行是否能够被其他应用程序进程读取? | 是 | 是 | 是 | 是 |
| 当前行是否能够被其他应用程序进程更新或删除? 5 | 见注释6 | 见注释6 | False | False |
注:
|
||||
隔离级别摘要
| 隔离级别 | 访问未落实的数据 | 不可重复的读取 | 幻像读 |
|---|---|---|---|
| 可重复的读 (RR) | 不可能 | 不可能 | 不可能 |
| 读稳定性 (RS) | 不可能 | 不可能 | 可能 |
| 游标稳定性 (CS) | 不可能 | 可能 | 可能 |
| 未落实的读 (UR) | 可能 | 可能 | 可能 |
| 应用程序类型 | 要求数据高度稳定 | 不要求数据高度稳定 |
|---|---|---|
| 读/写事务 | RS | CS |
| 只读事务 | RR 或 RS | UR |