快捷搜索:

DB2 9 基础(730 考试)认证指南,第 6 部分: 数据

事务

理解数据同等性

什么是数据同等性?回答这个问题的最佳措施是经由过程钻研示例。假定您的公司拥有多家连锁饭铺,公司用一个数据库来跟踪每家饭铺中的货物存储量。为了使货物采购历程更方便,数据库包孕每个连锁店的库存表。每当一家饭铺收到或用掉落一部分货物时,与该饭铺响应的库存表就会被改动以反应库存变更。

现在,假定从一家店调配多少瓶番茄酱到另一家店。为了准确地表示这一次库存调配,调出方饭铺表中存储的番茄酱瓶数必须削减,而接管方饭铺表中存储的番茄酱瓶数必须增添。假如用户削减了调出方饭铺库存表中的番茄酱瓶数,但没有增添接管方库存表中的番茄酱瓶数,则数据就会变得不同等。此时所有连锁店的番茄酱的总瓶数不再准确了。

假如用户忘怀了进行所有需要的变动(正如在前面的示例中一样),或者假如在用户进行变动的历程中系统崩溃了,又或者假如数据库利用法度榜样因为某种缘故原由过早地竣事了,数据库中的数据都邑变得不同等。当几个用户同时造访相同的数据库表时,也可能发生不同等。为了防止数据的不同等(尤其是在多用户情况中),DB2 的设计中集成了下列数据同等性支持机制:

事务

隔离级别

事务和事务界限

事务(也称为事情单元)是一种将一个或多个 SQL 操作组合成一个单元的可规复操作序列,平日位于利用法度榜样进程中。事务的启动和终止定义了数据库同等性点;要么将一个事务中履行的所有 SQL 操作的结果都利用于数据库(提交),要么完全取消并丢弃已履行的所有 SQL 操作的结果(回滚)。

应用从 Command Center、Script Center 或 Command Line Processor 运行的嵌入式 SQL 利用法度榜样和脚本,在可履行 SQL 语句第一次履行时(在建立与数据库的连接之后或在现有事务终止之后),事务就会自动启动。在启动事务之后,必须由启动事务的用户或利用法度榜样显式地终止它,除非应用了称为自动提交(automatic commit) 的历程(在这种环境下,发出的每个零丁的 SQL 语句被看作单个事务,它一履行就隐式地提交了)。

在大年夜多半环境下,经由过程履行 COMMIT 或 ROLLBACK 语句来终止事务。当履行 COMMIT 语句时,自从事务启动以来对数据库所做的统统变动就成为永远性的了 —— 即,它们被写到磁盘。当履行 ROLLBACK 语句时,自从事务启动以来对数据库所做的统统变动都被取缔,而数据库返回到事务开始之前所处的状态。不管是哪种环境,数据库在事务完成时都包管能回到同等状态。

必然要留意一点:虽然事务经由过程确保对数据的变动仅在事务被成功提交之后才成为永远性的,从而供给了一样平常的数据库同等性,但照样必要用户或利用法度榜样来确保每个事务中履行的 SQL 操作序列始终会导致同等的数据库。

COMMIT 和 ROLLBACK 操作的效果

正如在前面提到的,平日经由过程履行 COMMIT 或 ROLLBACK SQL 语句来终止事务。为了理解这些语句若何事情,钻研一个示例是有赞助的。

假如按所示的顺序履行下列 SQL 语句:

清单 1. 由三个事务组成的简单事情负载

CONNECT TO MY_DB

CREATE TABLE DEPARTMENT (DEPT_ID INTEGER NOT NULL, DEPT_NAME VARCHAR(20))

INSERT INTO DEPARTMENT VALUES(100, 'PAYROLL')

INSERT INTO DEPARTMENT VALUES(200, 'ACCOUNTING')

COMMIT

INSERT INTO DEPARTMENT VALUES(300, 'SALES')

ROLLBACK

INSERT INTO DEPARTMENT VALUES(500, 'MARKETING')

COMMIT

这将创建一个名为 DEPARTMENT 的表,它的布局如下所示:

DEPT_ID

DEPT_NAME

100

PAYROLL

200

ACCOUNTING

500

MARKETING

这是由于当履行第一个 COMMIT 语句时,创建名为 DEPARTMENT 的表并向 DEPARTMENT 表中插入两笔记录,这两个操作都邑变成永远性的。另一方面,当履行 ROLLBACK 语句时,删除插入 DEPARTMENT 表中的第三笔记录,该表返回到履行插入操作之前所处的状态。着末,当履行第二个 COMMIT 语句时,插入到 DEPARTMENT 中的第四笔记录成为永远性的,而数据库再次返回到同等状态。

正如可以从这个示例中看到的,提交或回滚操作只影响在这个操作所停止的事务内做出的变动。只要数据变动仍旧未被提交,其他用户和利用法度榜样平日就无法望见它们(也有例外环境,稍后我们将进行评论争论),并可以经由过程履行回滚操作取消它们。然则,一旦数据变动被提交了,其他用户和利用法度榜样就可以造访它们,并且再也不能经由过程回滚操作取消它们了。

不成功事务的效果

我们刚才已看到当经由过程 COMMIT 或 ROLLBACK 语句终止事务时会发生什么。然则,假如在事务完成前呈现系统故障,那会发生什么环境呢?在这种环境下,DB2 数据库治理法度榜样会取消所有未提交的变动,从而规复数据库同等性(假定在事务启动时存在这样的同等性)。图 1 比较了成功的事务和在成功终止之前掉败的事务的效果。

图 1. 比较成功的和不成功的事务

并发性和隔离级别

当多个用户造访同一数据库时会发生的征象

在单用户情况中,每个事务都是顺序履行的,而不会碰到与其他事务的冲突。然则,在多用户情况下,多个事务可以(而且经常)同时履行。是以每个事务都有可能与其他正在运行的事务发生冲突。有可能与其他事务发生冲突的事务称为交错的 或并行的 事务,而互相隔离的事务称为串行化 事务,这意味着同时运行它们的结果与一个接一个继续地运行它们的结果没有差别。在多用户情况下,在应用并行事务时,会发生四种征象:

损掉更新:这种环境发生在两个事务读取并考试测验更新同一数据时,此中一个更新会损掉。例如:事务 1 和事务 2 读取同一行数据,并都根据所读取的数据谋略出该行的新值。假如事务 1 用它的新值更新该行今后,事务 2 又更新了同一行,则事务 1 所履行的更新操作就损掉了。因为设计 DB2 的措施,DB2 不容许发生此类征象。

脏读:当事务读取尚未提交的数据时,就会发生这种环境。例如:事务 1 变动了一行数据,而事务 2 在事务 1 提交变动之前读取了已变动的行。假如事务 1 回滚该变动,则事务 2 就会读取被觉得是未曾存在的数据。

弗成重复的读:当一个事务两次读取同一行数据,但每次得到不合的数据值时,就会发生这种环境。例如:事务 1 读取了一行数据,而事务 2 在变动或删除该行后提交了变动。当事务 1 考试测验再次读取该行时,它会检索到不合的数据值(假如该行已经被更新的话),或发明该行不复存在了(假如该行被删除的话)。

幻像:当最初没有看到某个与搜索前提匹配的数据行,而在稍后的读操作中又看到该行时,就会发生这种环境。例如:事务 1 读取满意某个搜索前提的一组数据行,而事务 2 插入了与事务 1 的搜索前提匹配的新行。假如事务 1 再次履行孕育发生本来行集的查询,就会检索到不合的行集。

掩护数据库的同等性和数据完备性,同时又允许多个利用法度榜样同时造访同一数据,这样的特点称为并发性。DB2 数据库用来考试测验强制实施并发性的措施之一是经由过程应用隔离级别,它抉择在第一个事务造访数据时,若何对其他事务锁定或隔离该事务所应用的数据。DB2 应用下列隔离级别来强制实施并发性:

可重复的读(Repeatable Read)

读稳定性(Read Stability)

游标稳定性(Cursor Stability)

未提交的读(Uncommitted Read)

可重复的读隔离级别可以防止所有征象,然则会大年夜大年夜低落并发性的程度(可以同时造访同一资本的事务数量)。未提交的读隔离级别供给了最大年夜的并发性,然则后三种征象都可能呈现。

可重复读隔离级别

可重复读隔离级别是最严格的隔离级别。在应用它时,一个事务的影响完全与其他并发事务隔离:脏读、弗成重复的读、幻像都不会发生。当应用可重复的读隔离级别时,在事务履行时代锁定该事务以任何要领 引用的所有行。是以,假如在同一个事务中发出同一个 SELECT 语句两次或更多次,那么孕育发生的结果数据集老是相同的。是以,应用可重复的读隔离级其余事务可以多次检索同一行集,并可以对它们履行随意率性操作,直到由提交或回滚操作终止事务。然则,在事务存在时代,不容许其他事务履行会影响这个事务正在造访的任何行的插入、更新或删除操作。为了确保这种行径,锁定该事务所引用的每一行 —— 而不是仅锁定被实际检索或改动的那些行。是以,假如一个事务扫描了 1000 行,但只检索 10 行,则所扫描的 1000 行(而不仅是被检索的 10 行)都邑被锁定。

那么在现实情况中可重复读隔离级别是若何事情的呢?假定您应用 DB2 数据库跟踪旅店记录,包括房间预订和房价信息,还有一个基于 Web 的利用法度榜样,它容许顾客按 “先到先办事” 的原则预订房间。假如旅店预订利用法度榜样是在可重复读隔离级别下运行的,当顾客扫描某个日期段内的可用房间列表时,您(旅店经理)将无法变动那些房间在指定日期范围内的房价。同样,其他顾客也无法进行或取消将会变动该列表的预订(直到第一个顾客的事务终止为止)。然则,对付天生第一个顾客的列表时没有读取的任何房间记录,您可以改动房价。同样,其他顾客也可以进行或取消这些房间的预订。图 2 阐清楚明了这种行径。

图 2. 可重复读隔离级其余示例

读稳定性隔离级别

读稳定性隔离级别没有可重复读隔离级别那么严格;是以,它没有将事务与其他并发事务的效果完全隔离。读稳定性隔离级别可以防止脏读和弗成重复的读,然则可能呈现幻像。在应用这个隔离级别时,只锁定事务实际检索和改动的行。是以,假如一个事务扫描了 1000 行,但只检索 10 行,则只有被检索的 10 行(而不是所扫描的 1000 行)被锁定。是以,假如在同一个事务中发出同一个 SELECT 语句两次或更多次,那么每次孕育发生的结果数据集可能不合。

与可重复读隔离级别一样,在读稳定性隔离级别下运行的事务可以检索一个行集,并可以对它们履行随意率性操作,直到事务终止。在这个事务存在时代,其他事务不能履行那些会影响这个事务检索到的行集的更新或删除操作;然则其他事务可以履行插入操作。假如插入的行与第一个事务的查询的选择前提匹配,那么这些行可能作为幻像呈现在后续孕育发生的结果数据集中。其他事务对其他行所做的变动,在提交之前是弗成见的。

那么,读稳定性隔离级别会若何影响旅店预订利用法度榜样的事情要领呢?当一个顾客检索某个日期段内的所有可用房间列表时,您可以变动这个顾客的列表之外的任何房间的房价。同样,其他顾客可以进行或取消房间预订,假如第一个顾客再次运行同样的查询,其他顾客的操作可能会影响他得到的可用房间列表。假如第一个顾客再次查询同一个日期段内的所有可用房间列表,孕育发生的列表中有可能包孕新的房价或第一次孕育发生列表时弗成用的房间。图 3 阐清楚明了这种行径。

图 3. 读稳定性隔离级其余示例

游标稳定性隔离级别

游标稳定性隔离级别在隔离事务效果方面异常宽松。它可以防止脏读;但有可能呈现弗成重复的读和幻像。这是由于在大年夜多半环境下,游标稳定性隔离级别只锁定事务声明并打开的游标当前引用的行。

当应用游标稳定性隔离级其余事务经由过程游标从表中检索行时,其他事务不能更新或删除游标所引用的行。然则,假如被锁定的行本身不是用索引造访的,那么其他事务可以将新的行添加到表中,以及对被锁定行前后的行进行更新和/或删除操作。所获取的锁不停有效,直到游标重定位或事务终止为止。(假如游标重定位,原本行上的锁就被开释,并得到游标现在引用的行上的锁。)此外,假如事务改动了它检索到的任何行,那么在事务终止之前,其他事务不能更新或删除该行,纵然在游标不再位于被改动的行。与可重复读和读稳定性隔离级别一样,其他事务在其他行长进行的变动,在这些变动提交之前对付应用游标稳定性隔离级其余事务(这是默认的隔离级别)是弗成见的。

假如旅店预订利用法度榜样在游标稳定性隔离级别下运行,那么有什么影响呢?当一个顾客检索某个日期段内所有可用房间的列表,然后查看关于孕育发生的列表上每个房间的信息时(每次查看一个房间),您可以变动旅店中任何房间的房价,然则这个顾客当前正在查看的房间除外 (对付指定的日期段)。同样,其他顾客可以对任何房间进行或取消预订,然则这个顾客当前正在查看的房间除外 (对付指定的日期段)。然则,对付第一个顾客当前正在查看的房间记录,您和其他顾客都不能进行任何操作。当第一个顾客查看列表中另一个房间的信息时,您和其他顾客就可以改动他刚才查看的房间记录(假如这个顾客没有预订这个房间的话);但不能改动第一个顾客当前正在查看的房间记录。图 4 阐清楚明了这种行径。

图 4. 游标稳定性隔离级其余示例

未提交的读隔离级别

未提交的读隔离级别是最不严格的隔离级别。实际上,在应用这个隔离级别时,仅当另一个事务试图删除或变动被检索的行所在的表时,才会锁定一个事务检索的行。由于在应用这种隔离级别时,行平日维持未锁定状态,以是脏读、弗成重复的读和幻像都可能会发生。是以,未提交的读隔离级别平日用于那些造访只读表和视图的事务,以及某些履行 SELECT 语句的事务(只要其他事务的未提交数据对这些语句没有负面效果)。

顾名思义,其他事务对行所做的变动在已经提交之前对付应用未提交的读隔离级其余事务是可见的。然则,此类事务不能望见或造访其他事务所创建的表、视图或索引,直到那些事务被提交为止。类似地,假如其他事务删除了现有的表、视图或索引,那么仅当进行删除操作的事务终止时,应用未提交的读隔离级其余事务才能知道这些工具不再存在了。(必然要留意一点:当运行在未提交的读隔离级别下的事务应用可更新游标时,该事务的行径和在游标稳定性隔离级别下运行一样,并利用游标稳定性隔离级其余约束。)

那么未提交的读隔离级别对旅店预订利用法度榜样有什么影响呢?现在,当一个顾客检索某个日期段内的所有可用房间列表时,您可以变动旅店中任何房间任何日期的房价,而其他顾客也可以对任何房间进行或取消预订,包括第一个顾客当前正在查看的房间记录(对付指定的日期段)。别的,第一个顾客天生的房间列表可能包孕其他顾客正在预订(是以实际上弗成用)的房间。图 5 阐清楚明了这种行径。

图 5. 未提交的读隔离级别示例

选择精确的隔离级别

应用的隔离级别不仅影响数据库对并发性的支持若何,而且影响并发利用法度榜样的机能。平日,应用的隔离级别越严格,并发性就越小,某些利用法度榜样的机能可能会越低,由于它们要等待资本上的锁被开释。那么,若何抉摘要应用哪种隔离级别呢?最好的措施是确定哪些征象是弗成吸收的,然后选择能够防止这些征象发生的隔离级别:

假如正在履行大年夜型查询,而且不盼望并发事务所做的改动导致查询的多次运行返回不合的结果,则应用可重复的读隔离级别。

假如盼望在利用法度榜样之间得到必然的并发性,还盼望限制的行在事务履行时代维持稳定,则应用读稳定性隔离级别。

假如盼望得到最大年夜的并发性,同时不盼望查询看到未提交的数据,则应用游标稳定性隔离级别。

假如正在只读的表/视图/数据库上履行查询,或者并不介意查询是否返回未提交的数据,则应用未提交的读隔离级别。

指定要应用的隔离级别

只管隔离级别节制事务级上的行径,但实际上是在利用法度榜样级指定它们的:

对付嵌入式 SQL 利用法度榜样,在预编译时或在将利用法度榜样绑定到数据库(假如应用延迟绑定)时指定隔离级别。在这种环境下,应用 PRECOMPILE 或 BIND 敕令 的 ISOLATION 选项来设置隔离级别。

对付开放数据库连接(Open Database Connectivity,ODBC)和调用级接口(Call Level Interface,CLI)利用法度榜样,隔离级别是在利用法度榜样运行时经由过程调用指定了 SQL_ATTR_TXN_ISOLATION 连接属性的 SQLSetConnectAttr() 函数进行设置的。(别的,也可以经由过程指定 db2cli.ini 设置设置设备摆设摆设文件中的 TXNISOLATION 关键字的值来设置 ODBC/CLI 利用法度榜样的隔离级别;然则,这种措施不敷机动,不能像第一种措施那样为一个利用法度榜样中的不合事务改动隔离级别。)

对付 Java 数据库连接(Java Database Connectivity,JDBC)和 SQLJ 利用法度榜样,隔离级别是在利用法度榜样运行时经由过程调用 DB2 的 java.sql 连接接口中的 setTransactionIsolation() 措施设置的。

当没有应用这些措施显式指定利用法度榜样的隔离级别时,默认应用游标稳定性隔离级别。这个默认设置利用于从敕令行处置惩罚法度榜样(CLP)履行的 DB2 敕令、SQL 语句和脚本以及嵌入式 SQL、ODBC/CLI、JDBC 和 SQLJ 利用法度榜样。是以,也可以为从 CLP 履行的操作(以及通报给 DB2 CLP 进行处置惩罚的脚本)指定隔离级别。在这种环境下,隔离级别是经由过程在建立数据库连接之前在 CLP 中履行 CHANGE ISOLATION 敕令设置的。

在 DB2 UDB 8.1 及更高版本中,能够指定特定查询所用的隔离级别,措施是在 SELECT SQL 语句中加上 WITH [RR | RS | CS | UR] 子句。应用这个子句的简单 SELECT 语句示例如下所示:

SELECT * FROM EMPLOYEE WHERE EMPID = '001' WITH RR

假如利用法度榜样在大年夜多半时刻必要对照宽松的隔离级别(以支持最大年夜的并发性),然则对付此中的某些查询必须防止某些征象呈现,那么这个子句便是赞助您实现目标的好措施。

锁的事情道理

在 并发性和隔离级别 一节中,我们看到 DB2 经由过程应用锁 把事务彼此隔脱离来。锁是一种用来将数据资本与单个事务关联起来的机制,其用途是当某个资本与拥有它的事务关联在一路时,节制其他事务若何与该资本进行交互。(我们称与被锁定的资本关联的事务持有 或拥有 该锁。)DB2 数据库治理法度榜样用锁来禁止事务造访其他事务写入的未提交数据(除非应用了未提交的读隔离级别),并禁止其他事务在拥有锁的事务应用限定性隔离级别时对这些行进行更新。一旦获取了锁,在事务终止之前,就不停持有该锁;该事务终止时开释锁,其他事务就可以应用被解锁的数据资本了。

假如一个事务考试测验造访数据资本的要领与另一个事务所持有的锁不兼容(稍后我们将钻研锁兼容性),则该事务必须等待,直到拥有锁的事务终止为止。这被称为锁等待 事故。当锁等待事故发生时,考试测验造访数据资本的事务所做的只是竣事履行,直到拥有锁的事务终止和不兼容的锁被开释为止。

锁的属性

所有的锁都有下列基础属性:

object:object 属性标识要锁定的数据资本。DB2 数据库治理法度榜样在必要时锁定命据资本(如表空间、表和行)。

size:size 属性指定要锁定的数据资本部分的物理大年夜小。锁并不老是必须节制全部数据资本。例如,DB2 数据库治理法度榜样可以让利用法度榜样独有地节制表中的特定行,而不是让该利用法度榜样独有地节制全部表。

duration:duration 属性指定持有锁的光阴长度。事务的隔离级别平日节制着锁的持续光阴。

mode:mode 属性指定容许锁的拥有者履行的造访类型,以及容许并发用户对被锁定命据资本履行的造访类型。这个属性平日称为锁状态。

锁状态

锁状态确定容许锁的拥有者履行的造访类型,以及容许并发用户对被锁定命据资本履行的造访类型。表 1 阐清楚明了可用的锁状态,按照节制递增的序次排列。

表 1. 锁状态

锁状态(模式)

适用工具

描述

意向无(Intent None,IN)

表空间和表

锁的拥有者可以读取被锁定表中的数据(包括未提交数据),但不能变动这些数据。在这种模式中,锁的拥有者不获取行级锁;是以,其他并发利用法度榜样可以读取和变动表中的数据。

意向共享(Intent Share,IS)

表空间和表

锁的拥有者可以读取被锁定表中的数据,但不能变动这些数据。同样,由于锁的拥有者不获取行级锁;以是,其他并发的利用法度榜样可以读取和变动表中的数据。(当事务拥有表上的意向共享锁时,就在它所读取的每个行长进行共享锁定。)当事务没有表达更新表中行的意图时,就获取这种锁。(SELECT FOR UPDATE、UPDATE ... WHERE 和 INSERT 语句表达更新的意图。)

下一键共享(Next Key Share,NS)

锁拥有者和所有并发的事务都可以读(但不能变动)被锁定行中的数据。这种锁用来在应用读稳定性或游标稳定性事务隔离级别读取的数据上代替共享锁。

共享(Share,S)

表和行

锁拥有者和任何其他并发的事务都可以读(但不能变动)被锁定的表或行中的数据。只要表不是应用共享锁锁定的,那么该表中的单个行可以应用共享锁锁定。然则,假如表是用共享锁定的,则锁拥有者不能在该表中获取行级的共享锁。假如表或行是用共享锁锁定的,则其他并发事务可以读取数据,但不能对它进行变动。

意向互斥(Intent Exclusive,IX)

表空间和表

锁拥有者和任何其他并发的利用法度榜样都可以读取和变动被锁定表中的数据。当锁拥有者从表中读取数据时,它在所读取的每一行上获取一个共享锁,而在它更新的每一行上获取更新锁和互斥锁。其他并发的利用法度榜样可以读取和更新被锁定的表。当事务表达更新表中行的意图时,就获取这种锁。

带意向互斥的共享(Share With Intent Exclusive,SIX)

锁拥有者可以读取和变动被锁定表中的数据。锁拥有者在它更新的行上获取互斥锁,但不在它读取的行上获取锁;是以,其他并发的利用法度榜样可以读取但不能更新被锁定表中的数据。

更新(Update,U)

表和行

锁的拥有者可以更新被锁定表中的数据,而且锁的拥有者在它所更新的任何行上自动得到互斥锁。其他并发的利用法度榜样可以读取但不能更新被锁定表中的数据。

下一键弱互斥(Next Key Weak Exclusive,NW)

锁的拥有者可以读取但不能更新被锁定的行。当在非编目表的索引中插入行时,在表中的下一行上得到这种锁。

互斥(Exclusive,X)

表和行

锁的拥有者可以读取和变动被锁定的表或行中的数据。假如获取了互斥锁,则只容许应用未提交的读隔离级其余利用法度榜样造访被锁定的表或行。对付用 INSERT、UPDATE 和/或 DELETE 语句操作的数据资本,将获取互斥锁。

弱互斥(Weak Exclusive,WE)

锁的拥有者可以读取和变动被锁定的行。当向非编目表中插入行时,该行上将得到这种锁。

超级互斥(Super Exclusive,Z)

表空间和表

锁的拥有者可以变动表、删除表、创建索引或删除索引。当事务考试测验履行上述任何一种操作时,表上就自动得到这种锁。在开释这个锁之前,不容许其他并发事务读取或更新该表。

若何获取锁

在大年夜多半环境下,DB2 数据库治理法度榜样在必要锁时隐式地获取它们,是以这些锁在 DB2 数据库治理法度榜样的节制之下。除了应用未提交读隔离级其余环境外,事务从不必要显式地哀求锁。实际上,惟一有可能被事务显式地锁定的数据库工具是表。图 6 阐清楚明了用何种逻辑确定为所引用的工具获取什么类型的锁。

图 6. 若何获取锁

DB2 数据库治理法度榜样老是考试测验获取行级锁。然则,可以经由过程履行特殊形式的 ALTER TABLE 语句来改动这种行径,如下所示:

ALTER TABLE [TableName] LOCKSIZE TABLE

此中的 TableName 标识一个现有表的名称,所有事务在造访它时都要获取表级锁。

也可以经由过程履行 LOCK TABLE 语句,强制 DB2 数据库治理法度榜样为特定事务在表上获取表级锁,如下所示:

LOCK TABLE [TableName] IN [SHARE | EXCLUSIVE] MODE

此中的 TableName 标识一个现有表的名称,对付这个表应该获取表级锁(假定其他事务在该表上没有不兼容的锁)。假如在履行这个语句时指定了共享(SHARE)模式,就会得到一个容许其他事务读取(但不能变动)存储在表中的数据的表级锁;假如履行时指定了互斥(EXCLUSIVE)模式,就会得到一个不容许其他事务读取或改动存储在表中的数据的表级锁。

锁和机能

锁兼容性

假如数据资本上的一种锁状态容许在同一资本上放置另一个锁,就觉得这两种锁(或两种状态)是兼容的。每当一个事务持稀有据资本上的锁,而第二个事务哀求同一资本上的锁时,DB2 数据库治理法度榜样会反省两种锁状态以判断它们是否兼容。假如锁是兼容的,则将锁赋予第二个事务(假定没有其他事务在等待该数据资本)。然则,假如锁不兼容,则第二个事务必须等待,直到第一个事务开释它的锁为止,然后它才可以获取对资本的造访权并继承处置惩罚。(假如资本上有多个与新哀求的锁不兼容的锁,则第二个事务必须等到它们整个被开释为止。)请参阅 IBM DB2 9 Administration Guide: Performance 文档(或在 DB2 信息中间搜索 Lock type compatibility 主题)以获取关于各个锁之间是否兼容的特定信息。

锁转换

当事务考试测验造访它已经持有锁的数据资本,然则所需的造访模式必要比已持有的锁更严格的锁时,则所持有的锁的状态变动成更严格的状态。将已经持有的锁的状态变动成更严格状态的操作称为锁转换。发生锁转换是由于一个事务同一光阴内只能在一个数据资本上持有一个锁。

在大年夜多半环境下,对行级锁履行锁转换,转换历程相称简单。例如,假如持有共享(S)或更新(U)行级锁,然则必要互斥(X)锁,则所持有的锁将被转换成互斥(X)锁。但意向互斥(IX)锁和共享(S)锁是特例,由于无法确定此中哪个更严格。是以,假如持有此中一种行级锁但又必要另一种锁,则所持有的锁将转换成带意向互斥的共享(SIX)锁。假定所哀求的锁状态更严格的话,则类似的转换会使所哀求的锁状态成为持有锁的新状态。(仅当所持有的锁可以增添其严格性时,才会发生锁转换。)在转换了锁状态之后,锁处于所获取的最高状态,直到持有该锁的事务终止为止。

锁进级

所有的锁都必要存储空间;由于可用空间并不是无限的,以是 DB2 数据库治理法度榜样必须限定锁可以应用的空间(这是经由过程 maxlocks 数据库设置设置设备摆设摆设参数完成的)。为了防止特定命据库代理跨越已建立的锁空间限定,当获取的(随意率性类型的)锁过多时,会自动履行称为锁进级 的历程。锁进级是一种转换,它将同一表内几个零丁的行级锁转换成一个单一的表级锁。由于锁进级是在内部处置惩罚的,以是惟一可从外部检测到的结果可能只是对一个和多个表的并发造访削减了。

以下是锁进级的事情道理:当事务哀求锁而锁存储空间已满时,就选择与该事务相关联的一个表,让它获取一个表级锁,开释该表的所有行级锁(从而在锁列表数据布局中让出空间),并将表级锁添加到锁列表。假如这个历程所开释的空间不敷,则选择另一个表,重复这个历程,直到开释了足够的可用空间为止。这时,事务将获取所哀求的锁并继承履行。然则,假如在该事务的所有行级锁都已经进级之后,仍旧没有得到需要的可用锁空间,则(经由过程 SQL 差错编码)要求事务提交或回滚它启动以来所做的所有变动,然后事务终止。

锁超时

每当一个事务在特定命据资本(例如,表或行)上持有锁时,直到持有锁的事务终止并开释它所获取的所有锁之前,其他事务对该资本的造访都可能被回绝。假如没有某种锁超时检测机制,则事务可能无限日地等待锁的开释。例如,有可能呈现这种环境:一个事务在等待另一个用户的利用法度榜样所持有的锁被开释,而该用户脱离了他或她的事情站,但忘了履行一些容许利用法度榜样终止拥有锁的事务的交互。显然,此类环境会导致极差的利用法度榜样机能。要避免发生此类环境时阻碍其他利用法度榜样的履行,可以在数据库的设置设置设备摆设摆设文件中指定锁超时价(经由过程 locktimeout 数据库设置设置设备摆设摆设参数)。该参数节制任何事务等待获取所哀求的锁的光阴。假如在指定的光阴距离以前之后还未得到想要的锁,则等待的利用法度榜样接管一个差错,并回滚哀求该锁的事务。散播式事务利用法度榜样情况尤其轻易孕育发生此类环境;可以经由过程应用锁超时避免它们。

逝世锁

只管可以经由过程建立锁超时来避免一个事务无限日地等待另一个事务开释锁的环境,然则锁超时无法办理两个或更多事务对锁的争用。这种环境称为逝世锁 或逝世锁轮回。阐明逝世锁的发生缘故原由的最佳要领是举例阐明:假定事务 1 在表 A 上获取了互斥(X)锁,而事务 2 在表 B 上获取了互斥(X)锁。现在,假定事务 1 考试测验在表 B 上获取互斥(X)锁,而事务 2 考试测验在表 A 上获取互斥(X)锁。这两个事务的处置惩罚都将被挂起,直到批准第二个锁哀求为止。然则,由于在任何一个事务开释它今朝持有的锁(经由过程履行或回滚操作)之前,这两个事务的锁哀求都不会被批准,而且由于这两个事务都不能开释它今朝持有的锁(由于它们都已挂起并等待锁),以是它们都陷入了逝世锁轮回。图 7 阐清楚明了这个逝世锁场景。

图 7. 逝世锁轮回

当逝世锁轮回发生时,除非某些外部代理进行过问,否则所涉及的所有事务将无限日地等待开释锁。在 DB2 UDB 中,用于处置惩罚逝世锁的代理是称为逝世锁检测器 的异步系统后台进程。逝世锁检测器的惟一职责是定位和办理在锁定子系统中找到的任何逝世锁。每个数据库有自己的逝世锁检测器,它在数据库初始化历程中激活。激活之后,逝世锁检测器在大年夜多半光阴处于 “休眠” 状态,但会以预置的光阴距离被 “唤醒”,以确定锁定子系统中是否存在逝世锁轮回。假如逝世锁检测器在锁定子系统中发明逝世锁,则随机选择逝世锁涉及的一个事务,终止并回滚它。选择的事务收到一个 SQL 差错编码,它所得到的所有锁都被开释;这样,剩下的事务就可以继承履行了,由于逝世锁轮回已经被突破了。

锁粒度

正如先条件到的,每当一个事务在特定命据资本上持有锁时,在持有锁的事务终止之前,其他事务对该资本的造访都可能被回绝。是以,为了进行优化以获取最大年夜的并发性,行级锁平日比表级锁更好,由于它们所限定造访的资本要小得多。然则,由于所获取的每个锁都必要必然数量的处置惩罚光阴和存储空间,才能获取锁并进行治理,以是单个表级锁必要的开销比几个零丁的行级锁少。除非别的指定,否则默认环境下获取行级锁。

可以经由过程应用 ALTER TABLE ... LOCKSIZE TABLE、ALTER TABLE ... LOCKSIZE ROW 和 LOCK TABLE 语句节制锁的粒度(即,获取行级锁照样表级锁)。ALTER TABLE ... LOCKSIZE TABLE 语句供给了确定粒度的全局措施,它使得所有造访特定表中行的事务都获取表级锁。另一方面,LOCK TABLE 语句容许在单个事务级别获取表级锁。在应用这两种语句时,事务在必要锁时就获取单个共享(S)或互斥(X)表级锁。结果,由于只需获取和开释一个表级锁,而不是多个不合的行级锁,以是锁定机能平日会前进。然则,在应用表级锁时,假如长光阴运行的事务获取互斥而不是共享表级锁,那么并发性会低落。

事务和锁定

从锁定的角度来看,所有事务平日归为以下几类之一:

只读:这是指只读性的事务,它们包孕 SELECT 语句(它们本色上便是只读的)、指定了 FOR READ ONLY 子句的 SELECT 语句或意义虽不明确但由于在预编译和/或绑定历程中指定了 BLOCKING 选项而看作是只读的 SQL 语句。

倾向于变动:这是指有可能进行变动的事务,它们包孕指定了 FOR UPDATE 子句的 SELECT 语句或者那些意义虽不明确但由于 SQL 预编译器解释它的要领而看作是倾向于进行变动的 SQL 语句。

变动:这是指必然会进行变动的事务,它们包孕 INSERT、UPDATE 和/或 DELETE 语句,但不包括 UPDATE ... WHERE CURRENT OF ... 或 DELETE ... WHERE CURRENT OF ... 语句。

游标节制:这是指包孕 UPDATE ... WHERE CURRENT OF ... 和 DELETE ... WHERE CURRENT OF ... 语句的事务。

只读事务平日应用意向共享(IS)和/或共享(S)锁。另一方面,倾向于变动的事务将更新(U)、意向互斥(IX)和互斥(X)锁用于表,将共享(S)、更新(U)和互斥(X)锁用于行。变动事务每每应用意向互斥(IX)和/或互斥(X)锁,而游标节制的事务平日应用意向互斥(IX)和/或互斥(X)锁。

当 SQL 语句筹备履行时,DB2 优化器钻研各类满意该语句哀求的措施,并预计每种措施所涉及的履行资源。然后,DB2 优化器根据这一评估选择它觉得最优的造访计划(造访计划指定满意 SQL 哀求所需的操作,以及履行这些操作的顺序)。造访计划可以应用两种措施之一来造访表中的数据:经由过程直接地读取表(称为履行表 或关系扫描);或经由过程读取该表上的索引,然后检索特定索引项所引用的表行(称为履行索引扫描)。

DB2 优化器选择的造访路径(平日是根据数据库的设计确定的)会对所获取锁的数目和所应用的锁状态孕育发生显明的影响。例如,当应用索引扫描来查找特定行时,DB2 数据库治理法度榜样极有可能获取一个或多个意向共享(IS)行级锁。然则,假如应用表扫描,由于必须依次扫描全部表来找到特定行,以是 DB2 数据库治理法度榜样可能会选择获取单个共享(S)表级锁。

停止语

本教程旨在先容数据同等性的观点,以及 DB2 9 在单用户和多用户情况下用来掩护数据库同等性的各类机制。假如用户忘怀了进行所有需要的变动,或者假如在用户进行变动的历程中系统崩溃了,又或者数据库利用法度榜样因为某种缘故原由过早地竣事了,数据库都邑变得不同等。当几个用户同时造访同一数据库时,也可能发生不同等的环境。例如,一个用户可能在适当地更新所有表之前读取另一个用户的变动,并根据所读取的不是终极的数据值进行了一些不适当的操作或进行了差错的变动。为了防止数据不同等(尤其是在多用户情况中),DB2 9 的开拓职员将下列数据同等性支持机制合并到其设计中:

事务

隔离级别

事务(也称为事情单元)是一种将一个或多个 SQL 操作组织成一个单元的可规复序列,平日位于利用法度榜样进程中。事务的启动和终止定义了数据库同等性点;要么将事务中履行的所有 SQL 操作的结果都利用于数据库(提交),要么完全取消并丢弃已履行的所有 SQL 操作的结果(回滚)。在这两种环境下,数据库都包管在每个事务停止后处于同等的状态。

掩护数据库同等性和数据完备性,同时又允许多个利用法度榜样同时造访同一数据,这种特点称为并发性。在 DB2 中,并发性是经由过程应用隔离级别实现的。可以应用四种不合的隔离级别:

可重复的读

读稳定性

游标稳定性

未提交的读

可重复的读隔离级别可以防止所有征象,然则会大年夜大年夜低落并发性的程度(可以同时造访同一资本的事务数量)。未提交的读隔离级别供给了最大年夜的并发性,然则脏读、弗成重复的读和幻像都可能呈现。

除了隔离级别,DB2 经由过程对锁的应用在多用户情况下供给并发性。锁是一种用来将数据资本与单个事务关联起来的机制,其用途是节制其他事务在资本与拥有锁的事务相关联的环境下若何与资本进行交互。可以应用几种不合类型的锁:

意向无(IN)

意向共享(IS)

下一键共享(NS)

共享(S)

意向互斥(IX)

带意向互斥的共享(SIX)

更新(U)

下一键弱互斥(NW)

互斥(X)

弱互斥(W)

超级互斥(Z)

为了掩护数据完备性,DB2 数据库治理法度榜样隐式地获取锁,获取的所有锁都在 DB2 数据库治理法度榜样的节制之下。锁可以放置在表空间、表和行上。

为了进行优化以获取最大年夜的并发性,行级锁平日比表级锁更好,由于它们所限定造访的资本要小得多。然则,由于所获取的每个锁都必要必然数量的存储空间和处置惩罚光阴来进行治理,以是单个表级锁必要的开销比几个零丁的行级锁低。

您可能还会对下面的文章感兴趣: