`
evoleht
  • 浏览: 96373 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于DB2 数据库并发性(3)

    博客分类:
  • DB2
阅读更多

 

乐观锁定是与悲观锁定相对应的,所以要谈乐观锁定,就不可避免的要谈谈什么是悲观锁定,什么是乐观锁定?

 

所谓悲观锁定,就是查询表之后和尝试搜索的更新或删除记录操作之间的时间段挂起锁定的一种锁定策略。我们假设有这样一个场景,见图 56:



悲观锁定策略是:用户使用 RR/RS 隔离级别执行 SELECT 操作或以排他 exclusive 模式锁定表并执行查询操作(这里举例说明),通过游标得到一个结果集——对结果集记录加锁或者锁表,然后遍历这个游标,对这个结果集的每条记录做进一步的判断,符合条件的做更新操作,不符合条件的跳过,一直到游标遍历结束后,执行 COMMIT 操作,释放由 SELECT 操作获得的锁以及更新操作获得的锁,见图 57:



图 57. 悲观锁定策略

悲观锁定的优点就是能够保证实现一致且安全的更改。但是这种锁定策略的主要缺点就是在数据处理期间,一直占据着资源——被处理的资源的锁生命周期比较长,这样的话,可能会降低数据库的并发性,对于具有大并发用户的系统,需要等待资源释放的概率则会增加。

 

乐观锁定 是一项技术,它用于在选择 (SELECT) 行与更新或删除行之间未拥有行锁定的数据库应用程序。应用程序乐观地假定在更新或删除操作前未锁定的行不可能更改。如果行更改,那么更新或删除操作将失败,并且应用程序逻辑将通过重试查询操作(此处是举例说明)来处理这种故障。乐观锁定策略的主要优点是最小化给定资源对于其他事务的不可用时间,因此,它具有比悲观锁定更好的并行性,因为其他应用程序可以读写该行。它的一个缺点是应用程序中需要有更多的重试逻辑。

基于上述同样的场景,乐观锁定的策略是用户使用 CS/RS 隔离级别执行 SELECT 操作(此处是举例说明),得到一个结果集存放到客户端,然后执行 COMMIT 操作,释放对资源的锁定,然后在客户端遍历这个结果集,对这个结果集中的每条数据做进一步的判断,符合条件的做更新操作(如果确实这一行已经被修改了,那么更新操作将失败,应用程序逻辑将处理这些失败,例如,重新尝试查询),不符合条件的跳过,一直到遍历结束,执行 COMMIT 操作,释放相关资源上的锁,见图 58:



图 58. 乐观锁定策略

DB2 V9.5 之前版本的 DB2 应用程序只能通过构建搜索式 UPDATE 语句启用按值乐观锁定,该语句查找具有与所选值完全相同的值的行。如果行的列值已更改,那么搜索式 UPDATE 语句将失败。但是,按值乐观锁定具有一些缺点:

  • 标识主动错误信息,这可能会更新错误的行
  • 构建 UPDATE 搜索条件对应用程序来说很复杂
  • DB2 服务器根据值来搜索目标行的效率不高
  • 某些客户机类型与数据库类型之间的数据类型不匹配,例如,时间戳记不允许在搜索式 UPDATE 中使用所有列。

 

在 DB2 V9.5 之前,乐观锁定是按值乐观锁定,完全由应用程序本身逻辑控制实现的,而从 DB2 V9.5 开始支持增强的乐观锁定,除了应用程序本身逻辑控制实现之外,DB2 本身还提供了一些增强的机制来提高执行的效率。

DB2 V9.5 增加了速度更快的乐观锁定的支持,这种乐观锁定不会产生主动错误信息(误判),

DB2 V9.5 的乐观锁定特性最小化了给定资源对于其他事务的不可用时间,进一步改善了并发性。这一支持通过如下所示的新 SQL 函数、表达式和特性实现的:

  • 行标识符(RID_BITRID)内置函数:该内置函数可用于 SELECT 结果列表或谓词语句。例如,在谓词 WHERE RID_BIT(tab)=? 中,RID_BIT 等于谓词被实现为一种新的直接访问方法(避免了表扫描),从而可以更有效地定位行。在以前,被称为值乐观锁定的技术确定值的方式为:将所有选择(SELECT)的列值添加到谓词,然后应用某些惟一的列组合来筛选出单个行,这种通过表扫描方式访问方法效率较低。
  • ROW CHANGE TOKEN表达式:这种新的表达式返回一个标记作为 BIGINT 。这个标记表示某一行的修改序列中的一个相对点。应用程序可以将某行的当前行更改标记值与上次取回行时保存的行更改标记值进行比较,以判断行是否发生修改。表需要定义一个行修改时间戳列来保存时间戳值,是否提供行修改时间戳列将影响乐观锁定的行为,因为该列有助于将行更改标记的粒度从页级别提高到行级别,这对乐观锁定应用程序非常有利。

使用这种编程模型的应用程序将从增强的乐观锁定特性中获益。

 

在 DB2 V9.5 中,对普通的表即可使用针对乐观锁定的新 SQL 表达式和属性,但是,如果对普通的表不进行 DDL 修改的情况下,乐观锁定应用程序可能会产生更多的漏判。因此,要避免发生漏判,执行乐观锁定的目标表应执行以下任意一种操作来增加 ROW CHANGE TIMESTAMP 列:

  • 创建表时定义 ROW CHANGE TIMESTAMP 列
  • 对表进行修改以包含 ROW CHANGE TIMESTAMP 列

要在应用程序中启用增强的乐观锁定支持,需要执行以下基本步骤:

  • 在初始查询中,对要进行处理的所有行的行标识符和行更改标记执行 SELECT(使用 RID_BIT() 和 RID() 内置函数),使它们被包含在查询列表中。
  • 释放行锁定,以便其他应用程序可以对表执行选择、插入、更新和删除操作。
  • 通过在搜索条件中使用行标识符和行更改标记对目标行执行搜索式 UPDATE 或 DELETE,并乐观地假定在执行原始查询语句后未锁定的行尚未更改。
  • 如果行已更改,那么更新操作将失败,并且应用程序逻辑必须处理该故障。例如,应用程序将重试查询和更新操作。
注:行标识符、行更改标记的用途如下
        —搜索行标识符以直接访问目标行,而不是通过全表扫描或者索引扫描
        —搜索行更改标记以确认行的状态,即如果行更改标记没变,表明相应记录未被任何事务更改,
        反之表明记录已经被更改。
			

 

针对乐观锁定设计并已启用乐观锁定的应用程序,将按照下列操作顺序向数据库发送请求:



 

 
SELECT SALARY, row change token FOR STAFF, RID_BIT(STAFF) 
 INTO :h_SALARY, :h_rct, :h_rid 
 FROM STAFF WHERE ID = 240

 

在此方案中,应用程序首先读取所需的每行。我们准备在应用程序中使用乐观锁定策略,所以选择列表包括保存在 :h_rid 主变量中的行标识符值和保存在 :h_rct 主变量中的行更改标记值,见清单1

在启用了乐观锁定的情况下,应用程序乐观地假定更新或删除操作的任何目标行都保持不变。为了提高数据库并行性,应用程序使用下列其中一种方法除去行锁定:

  • 落实工作单元,在这种情况下行锁定将被除去
  • 使用 WITH RELEASE 子句关闭游标,在这种情况下行锁定将被除去
  • 使用较低的隔离级别:
    • 游标稳定性(CS),在这种情况下,在游标访存到下一行或结果表末尾后行未锁定。
    • 未落实的读(UR),在这种情况下,任何未落实的数据将具有新的(未落实)行更改标记值。如果回滚未落实的数据,那么已落实的旧行更改标记将是另一个值。

注: 假定通常不回滚更新,使用 UR 将允许最大并行性。

  • 断开与数据库的连接,因此释放应用程序的所有 DB2 服务器资源。

在释放查询操作所带来的行锁定之后,在应用程序逻辑中可能对上述查询获得的结果集进行相关判断处理,得到想要继续向下处理的行的行标识符和行更改标记,然后应用程序乐观地更新这些行:



 

UPDATE STAFF SET SALARY = SALARY * 1.2 WHERE row change token 
FOR STAFF = :h_rct AND RID_BIT(STAFF) = :h_rid

 

通过行标识符、行更改标记对目标行进行 UPDATE 是最快的访问方案,因为避免了对表进行扫描,而通过直接访存的方式(通过 ROWID 直接定位到该行):

				 RID_BIT(STAFF) = :h_rid

 

如果 RID_BIT() 谓词未找到行,那么表示行已删除并且更新操作由于未找到行而失败。

假定 RID_BIT() 谓词找到了行,那么在行更改标记未更改时,行更改标记谓词 FOR STAFF = :h_rct 将找到该行。如果在查询操作后行更改标记已更改,那么 UPDATE 语句将由于未找到行而失败。

下表总结了应用程序在启用了乐观锁定之后,可能出现的一些情况。



 

情况标识 操作 结果
情况 1 表中定义了行更改时间戳记列,并且其他应用程序未更改行。 由于行更改标记谓词成功找到 :h_rid 所标识的行,所以更新操作成功。
情况 2 表中定义了行更改时间戳记列。另一个应用程序在查询操作后在更新操作前更新了行,从而更新了行更改时间戳记列。 在查询操作时获得的行更改标记与行中当前行更改标记不匹配,因此 UPDATE 语句找不到行。
情况 3 表中定义了行更改时间戳记列。另一个应用程序更新了行,因此行具有新的行更改标记。此应用程序使用隔离级别 UR 查询行,并获取未落实的新的行更改标记。 此应用程序运行 UPDATE 语句,这将锁定等待,直到其他应用程序释放其行锁定为止。如果其他应用程序使用新标记落实更改,那么行更改标记谓词将成功,因此 UPDATE 语句成功。如果其他应用程序回滚到旧标记,那么行更改标记谓词将失败,因此 UPDATE 语句找不到行。
情况 4 表中未定义任何行更改时间戳记列。在查询操作后在更新操作前,在同一页面上更新、删除或插入了另一行。 该页面上的所有行共享一个行更改标记,该页面上任何行的更新,都会导致此页面上所有行的行更改标记更新。由于该页面上所有行的行更改标记值已更改,因此 UPDATE 语句匹配不到行。
如果本场景中添加了行更改时间戳记列,那么 UPDATE 语句将成功更新目标行。
情况 5 改变 (ALTER) 了表以便包含行更改时间戳记列,并且在改变操作后查询返回的行还未修改。另一个应用程序更新该行,从而在此过程中将行更改时间戳记列添加至该行(具有当前时间戳记)。 行更改标记谓词将先前生成的标记值与根据行更改时间戳记列创建的标记值进行比较,因为找不到匹配行,因此 UPDATE 语句执行失败。
情况 6 在查询操作后在更新操作前重组了表。 :h_rid 所标识的行标识找不到行,或者它包含具有另一个标记的行(经过重组,已经不是原来的那行),因此更新操作失败。这是无法避免的被动错误信息情况。 记录本身未被重组操作更新,记录中所有的列值并未变化,只是记录的位置发生了变更,因此重组后谓词的 RID_BIT 部分无法标识原始行(实际上 UPDATE 语句根据行标识符、行更改标识无法匹配到行),因此 UPDATE 操作失败。

 

 

假设有这样的一个场景:2 个数据库管理员同时接收到某个职员的请求,职员要求将自己的工作岗位变更一下。于是两名 DBA(DBA1/DBA2)通过人力资源系统更新 SAMPLE 数据库的 STAFF 表中的员工记录。此时存在一种可能,即两个 DBA 可能同时对同一名职员的记录进行更新。下面设计了几个场景,针对表 7 中所有的情况进行演示。

 

STAFF 表包含一个 ROW CHANGE TIMESTAMP 列 TS(后来添加)并且只有 DBA1 访问了该表。 DBA1 从 STAFF 表中查询数据并在稍后尝试将 ID 为 70 的员工的工作从 Sales 更新为 Mgr 。更新成功。


 

			
ALTER TABLE STAFF ADD COLUMN TS TIMESTAMP NOT NULL 
GENERATED ALWAYS FOR EACH ROW ON UPDATE AS 

ROW CHANGE TIMESTAMP




 

 
通过查询得到结果集的行标识符、时间标识符 , 然后执行 COMMIT 操作。
SELECT RID_BIT(STAFF),ROW CHANGE TOKEN FOR STAFF,ID,NAME,DEPT,JOB,TS
 FROM STAFF WHERE ID=70 
 COMMIT




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A000006000000000000000000FCF84F' 74904229642240 70 Rothman 15 Sales 0001-01-01-00.00.00.000000




 

 
使用 DBA1 之前查询出来的行标识符、时间标识符来更新行。
UPDATE STAFF SET JOB = 'Mgr' 
 WHERE RID_BIT(STAFF)=x'0A000006000000000000000000FCF84F' 
 AND ROW CHANGE TOKEN FOR STAFF=74904229642240




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A000006000000000000000000FCF84F' 141401933370756520 70 Rothman 15 Mgr 2009-07-02-15.10.17.921000

 

 

STAFF 表包含一个 ROW CHANGE TIMESTAMP 列 TS,并且 DBA1 和 DBA2 同时访问该表。 DBA1 从 STAFF 表中查询数据并执行提交操作,稍后尝试更新这些数据。然而,在 DBA1 查询数据到执行更新操作期间,DBA2 对相同的记录进行了更新。 DBA2 执行的更新成功,而随后 DBA1 执行的更新失败。



 

ALTER TABLE STAFF ADD COLUMN TS TIMESTAMP NOT NULL GENERATED
 ALWAYS FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A00400B00000000000000000465A5C1' 141401934713623382 70 Rothman 15 Mgr 2009-07-02-15.30.18.562006




 

 UPDATE STAFF SET JOB = 'Engineer' WHERE ID=70 
 OR 
 UPDATE STAFF SET JOB = 'Engineer' 
 WHERE RID_BIT(STAFF)= x'0A00400B00000000000000000465A5C1' 
 AND ROW CHANGE TOKEN FOR STAFF=141401934713623382




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A00400B00000000000000000465A5C1' 141401934875088080 70 Rothman 15 Engineer 2009-07-02-15.32.44.546000




 

 
使用 DBA1 之前查询得到的行标识符、时间标识符来更新行。
UPDATE STAFF SET JOB = 'Engi' 
 WHERE RID_BIT(STAFF)= x'0A00400B00000000000000000465A5C1' 
 AND ROW CHANGE TOKEN FOR STAFF=141401934713623382

 

DBA1 更新失败。由于 DBA2 执行了 UPDATE,ROW CHANGE TOKEN 发生了改变,因此当 DBA1 把执行查询时取回的标记与 DBA2 执行更新后的标记当前值进行比较时,无法找到匹配行,因此 DBA1 更新失败。

 

STAFF 表包含一个 ROW CHANGE TIMESTAMP 列 TS,并且 DBA1 和 DBA2 同时访问该表,DBA1 对行进行了更新,但还未提交修改,DBA2 使用 UR 隔离级别从 STAFF 表中查询数据,接着 DBA1 提交它做出的修改,然后 DBA2 尝试对相同的数据进行更新,DBA2 执行更新能够成功,因为 DBA2 之前执行脏读查询读取的是 DBA1 未提交的更新,这时变化后的 ROW CHANGE TOKEN 被读取到(当 DBA1 后来执行提交操作时,提交前产生变化的 ROW CHANGE TOKEN 不会再发生改变),所以后来 DBA2 执行更新操作能够找到匹配行,执行更新成功。然而,如果 DBA1 回滚更新操作而不是提交更新操作,那么 DBA2 的更新操作将失败。



 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A00000600000000000000000465ABC4' 141401934875088080 70 Rothman 15 Mgr 2009-07-02-15.32.44.546000




 

 UPDATE STAFF SET JOB = 'Chief' 
 WHERE RID_BIT(STAFF)= x'0A00000600000000000000000465ABC4' 
 AND ROW CHANGE TOKEN FOR STAFF=141401934875088080




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A00000600000000000000000465ABC4' 141401936241179608 70 Rothman 15 Chief 2009-07-02-15.53.03.343000

 

然后 DBA1 提交之前执行的 UPDATE 语句



 

commit

 

表 14. DBA1 查询提交后的结果

可以发现时间标识符与 DBA2 查询到的一致,实际上反映的都是新的时间标识符(不管是否提交)。

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A00000600000000000000000465ABC4' 141401936241179608 70 Rothman 15 Chief 2009-07-02-15.53.03.343000




 

 UPDATE STAFF SET JOB = 'GM' WHERE ID=70 
 OR 
 UPDATE STAFF SET JOB = 'GM' 
 WHERE RID_BIT(STAFF)= x'0A00000600000000000000000465ABC4' 
 AND ROW CHANGE TOKEN FOR STAFF=141401936241179608




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0A00000600000000000000000465ABC4' 141401937033810064 70 Rothman 15 GM 2009-07-02-16.00.55.250000

 

 

STAFF 表不包含 ROW CHANGE TIMESTAMP 列。 DBA1 查询一行 (ID=70),获得 ROW CHANGE TOKEN/RID_BIT(),然后 DBA2 更新了同一数据页中的其他记录 (ID=110, 这时 ROW CHANGE TOKEN 将发生改变,这个页中所有记录的 ROW CHANGE TOKEN 都是一样的,这时 ROW CHANGE TOKEN 是基于页的 ),然后,DBA1 尝试更新之前查询到的记录(通过 ROW CHANGE TOKEN/RID_BIT() 来定位),更新将会失败,因为 ROW CHANGE TOKEN 已经发生了改变,找不到匹配的记录了。



 

通过查询得到结果集的行标识符、时间标识符 , 然后执行 COMMIT 操作。
SELECT RID_BIT(STAFF),ROW CHANGE TOKEN FOR STAFF,ID,NAME,DEPT,JOB 
FROM STAFF WHERE ID = 70 
 COMMIT
 




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB
x'0A00400B00000000000000000465EFF9' 7632868011317133312 70 Rothman 15 Mgr

 

表 17. 同一数据页面上还存在的其他一些记录

下面几条记录都属于同一数据页面。

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB
x'0B00400B00000000000000000465EFF9' 7632868011317133312 80 James 20 Clerk
x'0C00400B00000000000000000465EFF9' 7632868011317133312 90 Koonitz 42 Sales
x'0D00400B00000000000000000465EFF9' 7632868011317133312 100 Plotz 42 Mgr
x'0E00400B00000000000000000465EFF9' 7632868011317133312 110 Ngan 15 Clerk




 

			
更新同一数据页面上的另外一条记录 (ID=110)
UPDATE STAFF SET JOB = 'Mgr' WHERE ID=110

 

表 18. DBA2 执行 UPDATE 语句后的结果

下表为同一数据页面上的部分记录,可以看到虽然只更新了ID=110这条记录,但是此页面上所有记录的 ROW CHANGE TOKEN 都共享 ID=110 这条记录的 ROW CHANGE TOKEN,也就是说表在没有时间戳记列存在的情况下,ROW CHANGE TOKEN 是基于页存在的。

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB
x'0A00400B00000000000000000465EFF9' -1300866274502377472 70 Rothman 15 Mgr
x'0B00400B00000000000000000465EFF9' -1300866274502377472 80 James 20 Clerk
x'0C00400B00000000000000000465EFF9' -1300866274502377472 90 Koonitz 42 Sales
x'0D00400B00000000000000000465EFF9' -1300866274502377472 100 Plotz 42 Mgr
x'0E00400B00000000000000000465EFF9' -1300866274502377472 110 Ngan 15 Clerk




 

			
通过之前查询得到的 ROW CHANGE TOKEN/RID_BIT() 定位。
 UPDATE STAFF SET JOB = 'Clerk' 
 WHERE RID_BIT(STAFF)= x'0A00400B00000000000000000465EFF9' 
 AND ROW CHANGE TOKEN FOR STAFF=7632868011317133312
 
 

 

更新将失败,已经找不到匹配的记录了,因为整个页面的时间标识符已经由于 DBA2 执行 UPDATE 语句而改变了。

 

STAFF 表包含 ROW CHANGE TIMESTAMP 列 TS,DBA1 和 DBA2 访问该表。 DBA1 从中查询一行,然后 DBA2 更新了同一数据页中的另外一行,接着 DBA1 更新之前查询到的那条记录,更新可以成功。



 

通过查询得到结果集的行标识符、时间标识符 , 然后执行 COMMIT 操作。
SELECT RID_BIT(STAFF),ROW CHANGE TOKEN FOR STAFF,ID,NAME,DEPT,JOB,TS 
FROM STAFF WHERE ID=120 
 COMMIT




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0F0000060000000000000000055F4927' 141402635178433027 120 Naughton 38 Clerk 2009-07-07-18.36.01.875011

 

表 20. 同一数据页面上还存在的其他一些记录

下面几条记录都属于同一数据页面。

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB
x'0B0000060000000000000000055F4927' 141402635178433023 80 James 20 Clerk
x'0C0000060000000000000000055F4927' 141402635178433024 90 Koonitz 42 Sales
x'0D0000060000000000000000055F4927' 141402635178433025 100 Plotz 42 Mgr
x'0E0000060000000000000000055F4927' 141402635178433026 110 Ngan 15 Clerk




 

更新同一数据页面上的另外一条记录。
 UPDATE STAFF SET JOB = 'VP' 
 WHERE RID_BIT(STAFF)= x'0D0000060000000000000000055F4927' 
 AND ROW CHANGE TOKEN FOR STAFF=141402635178433025




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0D0000060000000000000000055F4927' 141402635937539040 100 Plotz 42 VP 2009-07-07-18.47.21.812000




 

 
通过之前查询得到的 ROW CHANGE TOKEN/RID_BIT() 定位,更新成功。
UPDATE STAFF SET JOB = 'Mgr' 
 WHERE RID_BIT(STAFF)= x'0F0000060000000000000000055F4927' 
 AND ROW CHANGE TOKEN FOR STAFF=141402635178433027




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'0F0000060000000000000000055F4927' 141402643285428659 120 Naughton 38 Mgr 2009-07-07-20.28.53.281011

 

 

STAFF 表具有一个 ROW CHANGE TIMESTAMP 列 TS,并且只有 DBA1 访问该表。 DBA1 先从中查询一条记录用于以后更新它。然后表被离线重组。最后 DBA1 尝试更新数据,更新失败。更新失败是因为执行 REORG 后 RID_BIT 指向的已经不是原来的那一条记录,而且所有记录的 ROW CHANGE TIMESTAMP 列值也发生了变化,所以 DBA1 根据之前查询得到的 RID_BIT/ROW CHANGE TOKEN 已经找不到匹配的行,所以更新失败。



 

通过查询得到结果集的行标识符、时间标识符 , 然后执行 COMMIT 操作。
SELECT RID_BIT(STAFF),ROW CHANGE TOKEN FOR STAFF,ID,NAME,DEPT,JOB,TS 
FROM STAFF WHERE ID=150 
 COMMIT




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'1200400B00000000000000000465EFF9' 74904229642240 150 Williams 51 Sales 0001-01-01-00.00.00.000000




 

 REORG TABLE STAFF




 

乐观锁定表达式 STAFF 表
RID_BIT ROW CHANGE TOKEN ID NAME DEPT JOB ROW CHANGE TIMESTAMP
x'12000006000000000000000004A3C230' 141401962414435156 150 Williams 51 Sales 2009-07-02-21.59.04.093012

 

可以发现ID=150这条记录已经被移动到别的页面上去了,因为 RID_BIT() 已经发生了变化,而且 ROW CHANGE TOKEN 也发生了变化。



 

 
根据之前查询得到的行标识符、行更改标记执行更新操作,很明显,更新操作不能成功。
即使行标识符可能仍然指向有效的记录(已经不是原来的那条记录,因为这个位置可能已经被新的记录所占据),
但是行更改标记也已经发生了改变,所以使用之前查询得到的行标识符、行更改标记进行匹配,
匹配不到记录,所以更新操作不能成功。
UPDATE STAFF SET JOB = 'Mgr' 
 WHERE RID_BIT(STAFF)= x'1200400B00000000000000000465EFF9' 
 AND ROW CHANGE TOKEN FOR STAFF=74904229642240

 

结束语

 

为了避免在使用悲观锁定技术时可能引发的锁等待而导致的并发性问题,乐观锁定技术最小化了给定资源对于其他事务的不可用时间。通过使用乐观锁定,数据库管理器在完成读操作之后可以立即释放锁。

DB2 V9.5 支持更高效的乐观锁定,而且避免了误判的发生。这些支持通过行标识符(RID_BIT 或 RID)内置函数、行更改标识符 (ROW CHANGE TOKEN 表达式 ) 实现的。使用这种编程模型的应用程序可以从增强的乐观锁定特性受益,并且能够进一步增强并发性。

<!-- CMA ID: 419144 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-document-html-6.0.xsl -->

 

 

原文地址:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0908renzg/

分享到:
评论

相关推荐

    DB2数据库性能调整和优化 牛新庄 PDF

    深刻理解DB2的锁及并发机制、索引原理、数据库参数、优化器原理、SQL语句调优等内部机理才能针对性地快速提出解决问题的方法;快照、db2pd、db2expln及事件监控器等则是必须熟练掌握的工具。《DB2数据库性能调整和...

    DB2-730中文教材--适合数据库开发人员以及对数据库有兴趣的人

    • 第 6 部分:数据并发性 本教程讲解数据一致性的概念以及 DB2 在单用户和多用户环境中用来维护一致性的各种机制。 • 第 7 部分:XQuery 简介 本教程将解释几个基本的 XQuery 概念,并讲解如何编写处理 DB2 XML ...

    DB2数据库相关管理资料

    第一章 UDB概况 第二章 UDB的图形用户界面 第三章 数据存放 第四章 使用SQL语言创建数据对象 第五章 数据移动 第六章 数据库恢复 ...第八章 数据库的并发性控制 第九章 安全性控制 第十章 建立客户机服务器连接

    牛新庄: 循序渐进DB2:DBA系统管理、运维与应用案例 001

    客户端连通性、实例、数据库、表空间和缓冲池、数据移动、备份恢复、故障诊断、锁与并发,以及数据库安全都是本书关注的重点。在介绍这些DB2对象和概念的同时,作者尽可能从DBA日常工作的角度探究DB2数据库常规维护...

    牛新庄: 循序渐进DB2:DBA系统管理、运维与应用案例 002

    客户端连通性、实例、数据库、表空间和缓冲池、数据移动、备份恢复、故障诊断、锁与并发,以及数据库安全都是本书关注的重点。在介绍这些DB2对象和概念的同时,作者尽可能从DBA日常工作的角度探究DB2数据库常规维护...

    数据库并发控制机制.docx

    DB2,Mysql,Oracle中的并发控制机制,数据库的并发控制机制,顾名思义,是用来控制数据库的并发操作的机制。控制的目的是为了保证数据完整和数据一致性。

    db2 9 730 中文教程

    • 第 6 部分:数据并发性 本教程讲解数据一致性的概念以及 DB2 在单用户和多用户环境中用来维护一致性的各种机制。 • 第 7 部分:XQuery 简介 本教程将解释几个基本的 XQuery 概念,并讲解如何编写处理 DB2 XML ...

    循序渐进DB2.DBA系统管理、运维与应用案例.part1

    客户端连通性、实例、数据库、表空间和缓冲池、数据移动、备份恢复、故障诊断、锁与并发,以及数据库安全都是本书关注的重点。在介绍这些DB2对象和概念的同时,作者尽可能从DBA日常工作的角度探究DB2数据库常规维护...

    循序渐进DB2.DBA系统管理、运维与应用案例.part2

    客户端连通性、实例、数据库、表空间和缓冲池、数据移动、备份恢复、故障诊断、锁与并发,以及数据库安全都是本书关注的重点。在介绍这些DB2对象和概念的同时,作者尽可能从DBA日常工作的角度探究DB2数据库常规维护...

    循序渐进DB2.DBA系统管理、运维与应用案例

    客户端连通性、实例、数据库、表空间和缓冲池、数据移动、备份恢复、故障诊断、锁与并发,以及数据库安全都是本书关注的重点。在介绍这些DB2对象和概念的同时,作者尽可能从DBA日常工作的角度探究DB2数据库常规维护...

    构建DB2+DPF大型数据仓库经验谈

    DB2 DPF DB2多分区数据库.集群数据库,类似于ORACLE的RAC.但在架构上跟ORACLE RAC 存在很大的不同. DB2 DPF 采用非共享体系架构(Share-nothing)每个节点独立处理单一任务的能力,每个子 任务处理一部份数据.分区间...

    DB2 性能优化快速入门

    同时针对性能上的一些典型问题,如 DML 性能问题 ( 查询和插入操作 ), DDL 性能问题(建表,建索引),并发性问题等等,介绍一种渐进的分析方法,同时结合一些具体的优化案例进行分析以及成型的 DB2 调优工具 (DB2 ...

    MySQL数据库:数据库管理系统.pptx

    数据库的并发控制;数据字典(Data Dictionary,DD) 有关数据的数据描述,存放三级结构定义的数据库;Oracle SQL Server MySQL IBM DB2 Informix Sybase Access;速度快,MySQL数据库可能是目前能得到的最快的数据库。 ...

    数据库系统概论自己版.xmind

    存储信息时存在完整性问题(约束)、原子性问题(故障发生的不一致)、并发访问异常、安全性问题(用户选择性查看内容) 安全性:防止恶意更新或偷窃数据的企图 数据库访问 利用数据库管理系统提供的交互...

    Oracle数据库学习指南

    45. 在ORACLE7数据库并发控制技术的研究及其应用 46. 在SQLPlus中insert进的都是中文的,为什么一存入服务器后,再select出的就是???了 47. 在客户端处理Oracle的数据行加锁问题 48. 怎样查看init_ora文件 49. ...

    DB2 SQL介绍

    对DB2的主要产品、数据类型、基本的SQL语句与优化建议、高级SQL使用等进行了介绍,并研究了数据库的并发性

    数据库原理(第5版)

    通过这种方式学习,学生可以掌握适用于任意数据库的基本原则,包括小型的Microsoft Access数据库到大型的Oracle或DB2数据库。而且这一方法也避免了一个常见的问题:在同时介绍概念和产品时,学生容易混淆概念与产品...

    网络内存数据库

    接访问数据,从而获得极高的存取速度和极强的并发访问能力的数据库管理系统,在设计风格上兼容主流数据库(MS SQL SERVER、SYBASE)的特点,客户端通过TCP网络的方式来访问Cache Server。 Cache Server网络内存...

    DB2基础 学习资料

    资料有10个word文档,介绍得非常详细,对于自学DB2的朋友很有帮助 分为以下章节: 1、UDB概况 2、UBD的图形用户界面 3、数据存放 ...8、数据库的并发性控制 9、安全性控制 10、建立客户机服务器连接

    深入解析DB2--高级管理,内部体系结构与诊断案例.part1.rar

    7.5 最大化并发性 7.6 锁相关的性能问题总结 7.7 锁与应用程序开发 7.8 本章小结 第8章 索引设计与优化 8.1 索引概念 8.2 索引结构 8.3 理解索引访问机制 8.4 索引设计 8.5 索引创建原则与示例 8.6 影响索引性能...

Global site tag (gtag.js) - Google Analytics