当前位置: 老葡京网站娱乐 > 数据库 > db2教程 > 正文

DB2提供一种更好的方法实现乐观锁定

时间:2014-12-17 IBM

老葡京网站娱乐 www.sdguanhua.com 在 IBM i 6.1 版本,DB2 为用户提供一项新功能(ROW CHANGE列)可以为需要使用乐观锁的应用程序改进其算法。乐观锁定是一种基于网络数据库应用程序中广泛应用的技术,这些应用程序一定会读取数据但是只是有可能更新读取过的数据,但其不会维持一个与数据库的持久连接。因为应用并不维持一个持久的连接,用户不能够依靠行级锁为那些后续更新的行保持数据完整性。实现乐观锁定的一个常见方法是,把这个应用程序可能稍后要更新的那一行对应的列的所有值记录在缓存中,再将这些值在接下来的更新语句作为条件。

SELECT * FROM SCHEMA.TEST
C1 C2 C3 ...
10 12 33 ...
...UPDATE SCHEMA.TEST SET C1 = 12 WHERE C1=10 AND C2=12 AND C3=33 ...

如果另一个用户已经对当前行做了更新操作,这条更新语句将会失败,因为选择条件无法匹配被更新过新行的值。因此,DB2 不会覆盖任何之前的改变。运用乐观锁定,许多应用程序的用户能够并行的从数据库访问数据,同时允许一个单独的更新语句发生,而不用担心数据的丢失或者其它并发用户覆盖已更新过的数据。

存储一行的每一个属性对用户来说十分不便,但应用程序需要一种方式保证当其它用户对数据做出改变的时候,当前用户不会改变行中任何一列的值。幸运的是,从 DB2 for i 6.1 版本开始,有一种更简单的方法来确定从应用程序读取记录到当前为止数据库记录是否发生了改变。

这就是 DB2 for i 的新特性乐观锁定真正突出的地方。用户可以使用新的 PREPARE 属性设置或者客户端应用编程接口设置来使用这项支持。运用这种新的技术,DB2 将在返回的结果集中自动增加两列,这两列用于唯一地标识当前行和上次更新的时间。

应用程序无需为这更新时间列赋值;这一行每次更新后,这一特定列的值也会自动更新。

列 ROW CHANGE 支持

从版本6.1起,应用程序能够请求在任一查询的结果集中返回 ROW CHANGE 列。ROW CHANGE 列由两个独立的二进制列组成,分别是行变化特征(RCT)和行 ID(RID)。应用程序可以决定是否通过这两列来保证唯一性,或者在大多数情况下足够保证唯一性(将会在下面分别进行解释)。这些列可以是被应用程序显式地加到选择语句的列表里,也可以更方便地通过传入一个准备语句的属性完成添加:

STMT = ‘SELECT * FROM SCHEMA.TEST’;
ATT = ‘WITH ROW CHANGE COLUMNS ALWAYS DISTINCT’;
EXEC SQL DECLARE C1 CURSOR FOR S1;
EXEC SQL PREPARE S1 ATTRIBUTES :ATT FROM :STMT
EXEC SQL OPEN C1;

某些应用编程接口,比如 JAVA Database Connectivity(JDBC)和 iAccess .NET provider,也提供一些语句属性能够要求 DB2 在准备语句中添加这些列,从而查询语句本身不必改变。

行ID和行改变特征

RID 是一个 DB2 for i 为每一行自动添加的 BIGINT 类型的值。RID 标识行在表中的位置。

RCT 是一个派生出来的值。如果应用程序要求 RCT 和 RID 生成的值必须保证唯一性,那么表必须有一列是时间戳类型,而且拥有 FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP 属性:

ALTER TABLE TEST ADD COLUMN

RTS TIMESTAMP NOT NULL

GENERATED ALWAYS

FOR EACH ROW ON UPDATE AS ROW CHANGE TIMESTAMP

IMPLICITLY HIDDEN

当一个表包含这一特殊的时间戳类型的列,每一行返回的 RCT 的值来源于这一特殊列中存储的值。应用程序无需为此列赋值;每次行更新时,RCT 这一列的值随之自动更新。像其它的列一样,在 6.1 及之后的版本中这一列能够被定义成隐藏列,这就表示当对这个表做 SELECT * 查询的时候,这一列不会被返回。

请注意,即使有这一附加列,RCT 自身存储的值并不能保证唯一性,这是因为在某些情况下可能有多行返回相同的时间戳。然而,RCT 和 RID 两列在一起可以保证唯一性。

有些应用程序则并不绝对要求返回的 ROW CHANGE 列值的唯一性,因此不必为表增加一个 ROW CHANGE 时间戳类型的列,RCT 将会在 DB2 内部生成。

决定一个表是否应该增加特殊时间戳类型的列,一个需要考虑的因素就是周期性更新操作的数量。对于一个拥有繁重更新活动的表,增加一个ROW CHANGE 时间戳类型的列可能是值得的,可以减少应用程序必须处理的漏报(这里指一个行的更新操作结束而并没有被更新的情况)。另一方面,如果更新操作很少发生,你能够节省磁盘空间,取代依靠由内部算法生成的 RCT。

当使用 DB2 准备属性,从游标中取出数据时,RID 和 RCT 分别以列 QRID 和 QTOKEN 的名字自动地添加到每一行的末尾:

STMT = ‘SELECT * FROM SCHEMA.TABLE’;

ATT = ‘WITH ROW CHANGE COLUMNS ALWAYS DISTINCT’;

EXEC SQL DECLARE C1 CURSOR FOR S1;
EXEC SQL PREPARE S1 ATTRIBUTES :ATT FROM :STMT
EXEC SQL OPEN C1;EXEC SQL FETCH C INTO ...

C1 C2 C3 ... Q TOKEN Q RID

10 12 33 ... #### $$$$

...EXEC SQL UPDATE TEST SET C1 = 12 WHERE ROW CHANGE
TOKEN(SHEMA.TABLE)=#### AND RID(SCHEMA.TABLE)=$$$$

注意:RCT 和 RID 是以 BIGINT 类型返回的。