【IT168 技术】 隔离级别确定访问数据时如何锁定数据或使数据不受其他进程影响。该隔离级别将在工作单元运行期间生效。在执行OPENCURSOR的工作单元期间,使用由WITHHOLD子句的DECLARECURSOR语句声明的游标的应用程序将保持选定的隔离级别。DB2支持下列隔离级别:
*可重复读(RR: Repeatable Read)
*读稳定性(RS: Read Stability)
*游标稳定性(CS: Cursor Stability)
*未落实的读(UR: Uncommitted Read)
注:某些主机数据库服务器支持不落实隔离级别。对于其他数据库,此隔离级别的行为与未落实的读隔离级别一样。
每个隔离级别的详细说明按它们对性能的影响程度的降序排列,但按您访问和更新数据时需要加以关心的程度的升序排列。
可重复读RR (一句话:锁表,其他的session只能select别的都不能干)
可重复读(RR: Repeatable Read)会锁定应用程序在工作单元中引用的所有行。利用“可重复读”,在打开游标的相同工作单元内一个应用程序发出一个SELECT语句两次,每次都返回相同的结果。利用“可重复读”,不可能出现丢失更新、访问未落实的数据和幻像行的情况。
在该工作单元完成之前,“可重复读”应用程序可以尽可能多次地检索和操作这些行。但是,在该工作单元完成之前其他应用程序均不能更新、删除或插入可能会影响结果表的行。“可重复读”应用程序不能查看其他应用程序的未落实更改。
利用“可重复读”,将会锁定引用的每一行,而不仅仅是检索的那些行。执行了适当的锁定,因此其他应用程序不能插入或更新行(该行可能要添加到查询所引用的行的列表中,如果重新执行查询)。这将防止出现幻像行。例如,如果您扫描10000行并对它们应用谓词,尽管只有10行满足条件,但仍会锁定全部的10000行。
注:“可重复读”隔离级别确保在应用程序看到数据之前所有返回的数据都保持不变,即使使用了临时表或行分块也是如此。
由于“可重复读”可能获得和挂起大量锁定,因此这些锁定可能超出可作为locklist和maxlocks配置参数的有效结果的锁定数。为了避免锁定升级,优化器在认为很可能会发生锁定升级的时候,可能选择立即获得单个表级别锁定用于索引扫描。这就像数据库管理器代表您发出了一个LOCKTABLE语句一样。如果不想获得表级别锁定,确保有足够的锁定可用于该事务或使用“读稳定性”隔离级别。
评估引用约束时,在一些情况下,DB2将在内部把对外部表进行扫描所使用的隔离级别升级到“可重复读”(RR),而无论用户设置的隔离级别是什么。这将导致其他锁定在落实之前一直被挂起,从而增大了出现死锁或锁定超时的可能性。为了避免出现这种情况,建议您创建仅包含一列或多列外键的索引,从而允许RI扫描使用此索引。
读稳定性RS (一句话:只锁定被检索的行,锁定后的行其他进程可读但不能更改,表的其他行可以dml)
读稳定性(RS: Read Stability)只锁定应用程序在工作单元中检索的那些行。它确保在某个工作单元完成之前,在该工作单元运行期间的任何限定行读取不被其他应用程序进程更改,且确保不会读取由另一个应用程序进程所更改的任何行,直至该进程落实了这些更改。也就是说,不可能出现“不可重复读”情形。
与可重复读不同,使用“读稳定性”时,如果您的应用程序多次发出相同的查询,那么有可能看到附加的幻像行(幻像读现象)。重新引用扫描10000行的示例时,“读稳定性”只锁定限定的行。这样,使用“读稳定性”时,只检索10行,且只对那十行挂起锁定。将它与“可重复读”对比,在本示例中,可重复读会在所有的10000行上挂起锁定。挂起的锁定可以是共享、下次共享、更新或互斥锁定。
注:“读稳定性”隔离级别确保在应用程序看到数据之前所有返回的数据保持不变,即使使用了临时表或行分块也是如此。
“读稳定性”隔离级别的其中一个目标是提供较高并行性程度以及数据的稳定视图。为了有助于达到此目标,优化器确保在发生锁定升级前不获取表级锁定。
“读稳定性”隔离级别最适用于包括下列所有特征的应用程序:
*在并发环境下运行
*需要限定某些行在工作单元运行期间保持稳定
*在工作单元中不会多次发出相同的查询,或者在同一工作单元中发出多次查询时并不要求该查询获得相同的回答。
游标稳定性CS (单行锁,缺省的隔离级别)
游标稳定性(CS: Cursor Stability)当在行上定位游标时会锁定任何由应用程序的事务所访问的行。此锁定在读取下一行或终止事务之前有效。但是,如果更改了某一行上的任何数据,那么在对数据库落实更改之前必须挂起该锁定。
对于具有“游标稳定性”的应用程序已检索的行,当该行上有任何可更新的游标时,任何其他应用程序都不能更新或删除该行。“游标稳定性”应用程序不能查看其他应用程序的未落实更改。
再次引用扫描10000行的示例,如果使用“游标稳定性”,将只锁定当前游标位置以下的行。当游标移离该行时,也就除去了该锁定(除非更新该行)。
使用“游标稳定性”,可能会出现不可重复读和幻像读现象。“游标稳定性”是缺省隔离级别,且应在需要最大并行性,但只看到其他应用程序中的已落实行的情况下才使用。
未落实的读UR
未落实的读(UR: Uncommitted Read)允许应用程序访问其他事务的未落实的更改。除非其他应用程序尝试删除或改变该表,否则该应用程序也不会锁定正读取的行而使其他应用程序不能访问该行。对于只读和可更新的游标,“未落实的读”的工作方式有所不同。
只读游标可访问大多数其他事务的未落实的更改。但是,当该事务正在处理时,正由其他事务创建或删除的表、视图和索引不能使用。其他事务的任何其他更改在落实或回滚前都可被读取。
注:“未落实的读”隔离级别下的可更新操作的游标将按隔离级别是游标稳定性的方式工作。
当它使用隔离级别UR运行程序时,应用程序可以使用隔离级别CS。发生这种情况的原因是因为在应用程序中使用的游标是模糊游标。由于BLOCKING选项,可以将模糊游标升级为隔离级别CS。BLOCKING选项的缺省值是UNAMBIG。这意味着将模糊游标当作可更新的,并且隔离级别升级为CS。要防止此升级,有两种选择:
*修改应用程序中的游标。以便这些游标是非模糊游标。将SELECT语句更改为包括FORREADONLY子句。
*将模糊游标保留在应用程序中,但是预编译程序或使用BLOCKINGALL和STATICREADONLYYES选项绑定它以允许在运行该程序时将任何模糊游标视为只读游标。
如对扫描10000行的“可重复读”给出的示例一样,如果使用“未落实的读”,那么不需要任何行锁定。
使用“未落实的读”,可能出现不可重复读行为和幻像读现象。“未落实的读”隔离级别最常用于只读表上的查询,或者若仅执行选择语句且不关心是否可从其他应用程序中看到未落实的数据时也最常用。
隔离级别的摘要
下表按不期望的结果概述了几个不同的隔离级别。
下表提供了简单的试探方法,以帮助您为应用程序选择初始隔离级别。首先考虑下表列示的方法,并参阅先前对各级因素的讨论,可能会找到另一个更适合的隔离级别。
表2.选择隔离级别的准则
为一个应用程序选择适当的隔离级别对于该应用程序避免无法容忍的现象很重要。因为获取和释放锁定所需的CPU和内存资源随隔离级别的不同而不同,所以此隔离级别不但影响应用程序之间的隔离程度,而且还影响个别应用程序的性能特征。潜在的死锁情况随隔离级别的不同而不同。