DB2隔离级别和锁 - 图文(7)

2019-02-15 22:51

RID_BIT ROW CHANGE TOKEN EMPNO FIRSTNME LASTNAME PHONENO ROW CHANGE TIMESTAMP x'04004001000000000000000000FA9023' 141285673714388072 000010 CHRISTINE HAAS 10922008-12-20 18:22:25.593000 x'05004001000000000000000000FA9023' 74904229642240 000020 MICHAEL THOMPSON 3476 0001-01-01 00:00:00.000000 x'06004001000000000000000000FA9023' 74904229642240 000030 SALLY KWAN 4738 0001-01-01 00:00:00.000000 (3) MANAGER1 对同一数据页上的另一行执行下面的 UPDATE 语句: UPDATE EMPLOYEE SET (FIRSTNME,LASTNAME,PHONENO) = ('MICHAEL','THOMPSON','9012') WHERE RID_BIT(EMPLOYEE)=x'04004001000000000000000000FA9023' AND ROW CHANGE TOKEN FOR EMPLOYEE=74904229642240 (4) MANAGER1 执行 UPDATE 可以成功,成功后的输出结果如下: RID_BIT ROW CHANGE TOKEN EMPNO FIRSTNME LASTNAME PHONENO ROW CHANGE TIMESTAMP x'04004001000000000000000000FA9023' 141285673714388072 000010 CHRISTINE HAAS 1092 2008-12-20 18:22:25.593000 x'05004001000000000000000000FA9023' 141285673726689984 000020 MICHAEL THOMPSON 9012 2008-12-20 18:22:37.312000 x'06004001000000000000000000FA9023' 74904229642240 000030 SALLY KWAN 4738 0001-01-01 00:00:00.000000 场景 6 EMPLOYEE 表具有一个 ROW CHANGE TIMESTAMP 列,并且只有 MANAGER1 访问该表。 MANAGER1 从中选择若干行并尝试更新它们。然而,从他进行选择到更新期间,表被离线重组。稍后,当 MANAGER1 尝试更新数据时,更新失败。行更新失败是因为执行REORG后 ROW CHANGE TIMESTAMP 列发生了变化。这个场景的主要步骤如下: (1) 执行下面的命令重组 EMPLOYEE 表: REORG TABLE EMPLOYEE (2) 重组表 EMPLOYEE 后,EMPLOYEE 表的 ROW CHANGE TIMESTAMP 列发生变化,输出结果如下所示: RID_BIT ROW CHANGE TOKEN EMPNO FIRSTNME LASTNAME PHONENO ROW CHANGE TIMESTAMP x'04004001000000000000000000FA9023' 141285781563232400 000010 CHRISTINE HAAS 3978 2008-12-21 11:29:30.250000 x'05004001000000000000000000FA9023' 141285781563232401 000020 MICHAEL THOMPSON 3476 2008-12-21 11:29:30.250001 x'06004001000000000000000000FA9023' 141285781563232402 000030 SALLY KWAN 4738 2008-12-21 11:29:30.250002 (3) MANAGER1 在运行REORG后尝试更新数据,SQL 语句如下: UPDATE EMPLOYEE SET (FIRSTNME,LASTNAME,PHONENO) = ('CHRISTINE','HAAS','1092') WHERE RID_BIT(EMPLOYEE)=x'04004001000000000000000000FA9023' AND ROW CHANGE TOKEN FOR EMPLOYEE=74904229642240

MANAGER1 执行更新失败,因为在 MANAGER1 执行SELECT 和 UPDATE期间,另一个任务对表执行了离线重组,因此在将执行SELECT时检索到的标记和当前标记进行比较时,ROW CHANGE

TOKEN谓词失败。因此,UPDATE语句无法找到具有ROW CHANGE TOKEN的行,这些行是在发生REORG之前检索得到的。

乐观锁总结

为了避免在使用悲观锁定技术时可能引发的锁等待问题,乐观锁定技术最小化了给定资源对于其他事务的不可用时间。由于数据库管理器可以确定行发生修改的时间,它可以确保数据完整性,同时限制持有锁的时间。通过使用乐观并发控制,数据库管理器在完成读操作之后可以立即释放行或页锁。 DB2 V9.5 支持进行更简便和快捷的乐观锁定,而且避免了误判的发生。这些支持通过行标识符 (RID_BIT或RID) 内置函数、ROW CHANGE TOKEN表达式、基于时间的更新检测和隐式隐藏列实现。使用这种编程模型的应用程序可以从增强的乐观锁定特性要受益,并且能够进一步增强并发性。其实 DB2 V9.5 的乐观锁机制在某种程度上类似 Oracle 数据库的 SCN 实现机制,相信 DB2 在以后的版本中会对这种技术做进一步的改进,从而实现对某行操作的多版本读。

回页首

6.4 内部锁

我们在数据库中经常会看到一些内部锁,最常见的是内部 P 锁和内部 V 锁,下面来介绍这些内部锁。

6.4.1 内部方案锁 (Internal Plan Lock)

首先,我们先做一个例子,如果输出结果如下所示:

C:\\>db2 +c update employee set salary=1234 where empno='000100'

DB20000I SQL 命令成功完成。 -- 注:执行一条新的SQL语句,+C不提交,否则锁消失了 C:\\>db2 get snapshot for locks on sample----- 监控加锁情况 数据库锁定快照 数据库名称 = SAMPLE

数据库路径 = C:\\DB2_01\\NODE0000\\SQL00001\\ 输入数据库别名 = SAMPLE 挂起的锁定 = 3

当前已连接的应用程序 = 2

……………………………………………… . 节省篇幅 , 略………………………………………………………………………… 锁定名称 = 0x53514C4332473133B7F3CE3241 锁定属性 = 0x00000000

发行版标志 = 0x40000000 锁定计数 = 1 挂起计数 = 0 锁定对象名 = 0 对象类型=内部方案锁定(Internal Plan Lock)方式 = S ……………………………………………… . 节省篇幅 , 略………………………………………………………………………… 大家知道无论数据库是在处理静态 SQL 还是动态 SQL,DB2 的相关组件都需要去访问程序包信息和相应的 SQL 查询访问计划。那么默认情况下,DB2 都会去给相应的 Package Cache 加内部 P 锁,以防止其他的什么操作将正在使用的 Package 删除,毫无疑问的是,这样的一个锁对性能多少会有影响,但影响是很小的。 DB2 的变量注册参数里面有个配置参数是 DB2_APM_PERFORMANCE 。如果这个值被设置为 ON,则会启用无包锁定方式。此方式允许全局查询高速缓存运行,而不必使用包锁定,这些锁定是内部系统锁定,可以保护高速缓存的包条目不被除去。无包锁定方式在一定程度上可以提高性能,但它不允许执行某些数据库操作。这些被禁止的操作可能包括:使包无效的操作、使包不起作用的操作、PRECOMPILE、BIND 和 REBIND 。所以,在这里只是让大家知道这个变量和了解程序包高速缓存的内部工作机制,但是不建议大家修改这个值。 在上面的例子中,我们可以看到有一个内部 P 锁。这是因为无论我们执行的是一条静态 SQL 语句还是一条动态 SQL 语句,在执行过程中,都要依次经过语法检查、语义检查、权限检查、查询重写、下推分析等阶段,最后优化器根据统计信息、配置参数、索引等情况为这条 SQL 语句生成一个成本最优的执行方案。该方案决定了使用什么扫描方式、访问表的顺序、表的连接方式和使用哪个索引。那么为了保证这条 SQL 语句在下次执行时不再重复上述步骤,数据库会把这条 SQL 语句的执行方案存放在程序包高速缓存中 (PCKCACHE_SZ) 中,在存放的时候它首先需要在程序包高速缓存中申请一块内存,然后把执行方案 INSERT 到该内存中。在申请时它要在这块内存中加一个锁以确保在 SQL 语句执行期间,这块内存不被别的应用删除 (DROP),这就是内部 P 锁的作用 ( 在 Oracle 数据库中这种锁叫 LATCH 。 LATCH 是对内存加的锁,不是对数据库对象 ( 表、行 ) 加的锁,所以这种锁我们可以忽略 ) 。 6.4.2 内部 V 锁 (Internal Variation Lock) 当执行动态 SQL 语句时,对 SQL 的处理会在程序包的缓存中存储一个变量条目,为了保证这个变量条目在事务处理期间的有效性,DB2 会为它赋予一个内部 V 锁。下面我们看一个例子,在一个 B/S 结构中,前台运行 Java 应用,应用通过连接池发起动态 SQL 语句到数据库。假设某个时刻应用执行如下 SQL 语句: update account set transdate= date(current timestamp) -? day 在这条 SQL 语句执行期间,我们执行“ get snapshot for locks ”监控发现如下锁的信息, Application handle = 40 Application ID = 0A0B0A49.EB44.020821194232 Sequence number = 0001 Application name = db2jcc Authorization ID = DB2INST1Application status = Compiling --注:应用程序正在编译 Status change time = 08-21-2008 9:52:10.800363 Application code page = 819 Locks held = 2 Total wait time (ms) = 0 List Of Locks Lock Object Name = 0 Node number lock is held at = 0Object Type = Internal V Lock --注:内部V锁 Tablespace Name = Table Schema = Table Name = Mode = S Status = Granted Lock Escalation = NO Lock Object Name = 0 Node number lock is held at = 0Object Type = Internal P Lock --注:内部P锁 Tablespace Name = Table Schema = Table Name = Mode = S Status = Granted Lock Escalation = NO --------------------------------- 略 -----------------------------------

通过上面的锁的信息的监控,我们发现存在内部 V 锁。下面我们来讲解内部 V 锁的加锁机制。 在“ update account set transdate=date(current timestamp) -? day ”这条 SQL 语句传递给优化器编译 (COMPILING) 时,我们需要为这条 SQL 语句提供一个编译环境,这个编译环境包括把特殊的寄存器 (CURRENT STAMP) 变量转变成真正的值;表 ACCOUNT 没有模式名,需要使用 DEFAULT QUALIFIER 用作模式;我们使用了 DATE 函数,需要知道该函数的函数路径 (CURRENT FUNCTION PATH) ;我们使用了参数标记 ( ? ),需要把参数标记转变成真正的值。上述的每一个变量都需要一个内部 V 锁来保证在该 SQL 执行期间,这些变量不被别的 DDL 语句修改或者被程序包缓存空间管理算法删除。

6.4.3 内部 S 锁

DB2 中的很多动作实际是作为一个事件来记录的,那么事件的序号的机制保证这些事件是按照一定的正确的顺序来运转。也就是一个特定的代理 AGENT 只能一次处理一个特定的事件。

在分区数据库环境中,这样的内部 S 锁通常是用来在执行无效的 DDL 语句的时候,初始化特定的临时表空间。

在 DB2 V7 到现在的版本中,这样的内部 S 锁实际是作用于临时表空间上的 S 锁。一个特定应用程序都会有自己的一个存在于特定临时表空间里面的临时表,这样的内部 S 锁作用其上,以控制其不被其他的操作删除了相应的临时表空间。内部 S 锁通常用在分区数据库环境中。

6.4.4 内部 C 锁

内部 C 锁 (Internal Catalog Cache Lock) 是为编目缓存 (CATALOGCACHE_SZ) 中某个条目而得到的一个锁,这样的锁用来在编目缓存中参照或者修改任意的条目的保证其完整性和一致性。 DB2 的编目缓存用来缓存系统编目表的信息,以加速 SQL 语句的编译速度和缩短 SQL 语句的编译过程。

从 DB2 组件设计的角度来看,当编目缓存的条目信息被锁的时候,相应的系统编目表的数据行也必须被锁。

所以我们的内部 C 锁的格式和常规的表的数据行的锁的格式是一样的,如下所示: 表空间id+数据库对象id+数据行id 只不过在这样的锁的名字中,会有个 'C' 用来表示这个锁是 Catalog Cache 锁。“ R ”用来表示这个锁是数据记录的锁。在一个事务的处理过程中,如果系统编目表的信息被更新,那么相应的编目缓存的条目的锁就是 X 锁,通常情况下,只会在相应的条目上加 S 锁。 DB2 内部保证在 SQL 处理的过程中只需要对编目缓存持有 S 锁。当 SQL 编译结束,相应的执行段被创建时,DB2 的这个相应的编目缓存条目的锁就会被释放。下面我们举一个内部 C 锁的例子,输出结果如下: C:\\>db2 +c create table t2(id int) DB20000I SQL 命令成功完成。

在另外一个窗口中使用“ get snapshot for locks ”监控信息的输出结果,如下所示 ( 部分 ):

--------------------------------- 省略 ----------------------------------- 锁定名称 =0x0000050004431A00600E407D43 --

注:Tablespaceid+Tableid+RID锁定属性 = 0x00000000 发行版标志 = 0x40000000 锁定计数 = 255 挂起计数 = 0 锁定对象名 = 0

对象类型 = 内部目录高速缓存锁定 方式 = X

锁定名称 = 0x0100000000000000600E407D43 --

注:43代表Catalog Cache Lock锁定属性 = 0x00000000 -- 注:52 代表是行锁 (row lock) 发行版标志 = 0x40000000 锁定计数 = 255 挂起计数 = 0 锁定对象名 = 0

对象类型 = 内部目录高速缓存锁定 方式 = X

--------------------------------- 省略 ----------------------------------- 锁定名称 = 0x0300000000000000000000004F 锁定属性 = 0x00000000 发行版标志 = 0x40000000 锁定计数 = 2 挂起计数 = 0 锁定对象名 = 0

对象类型 = 内部对象表锁定 方式 = IN

锁定名称 = 0x03001600000000000000000054 锁定属性 = 0x00000000


DB2隔离级别和锁 - 图文(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:自然辩证法复习题及答案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: