在另一语句句柄的写冲突下的常规读游标
应用程序可有多个语句句柄同时对同一个表执行读写操作。当一个句柄对该表执行写操作(例如,UPDATE、DELETE 或 INSERT)而另一个句柄也正在执行读或写操作时,将发生冲突。DB2 Everyplace 采用的行为是首先执行读操作并且总是读取最新的数据。它忽略写冲突(不管该写冲突是否在使用索引)。 例如,假定应用程序有两个语句句柄。句柄 #1 用来从表 T 取装行,而句柄 #2 用来从同一个表删除某些行。很可能已由不同的线程创建了每个句柄(例如,在 Java 线程环境中)。
以下是可能的方案:
// Fetch 2 rows from table T Statement handle 1: execute "SELECT A FROM T WHERE primary_key < 10" Statement handle 1: fetch one row; fetch another row // Delete some rows in table T Statement handle 2: prepare "DELETE FROM T WHERE primary_key = ?" Statement handle 2: execute // Continue to fetch one more row from T Statement handle 1: fetch one row
此时在执行中,语句句柄 #1 将能够继续取装下一行(如果有的话),不管索引是否正被使用。在上面的方案中,因为存在主键而使得索引正被使用。解决方法是 DB2 Everyplace 将尝试使用句柄 #1 的当前位置重新定位其游标位置(在前进之前)。如果当前位置不再存在(例如,该行已被另一语句句柄删除),则游标在取装时仅需前进至下一位置。同样,如果下一位置被另一语句句柄删除,游标可以跳过该“空位”以进至下一位置。
另一语句句柄的写冲突下的可滚动游标
考虑与上一节中类似的示例,但在此示例中读游标将是可滚动游标。如果它是“不敏感”的可滚动游标,这就不是问题,原因是结果集不会按定义更改。如果游标不是“不敏感”的,则采用的行为将与上面描述的常规读游标相似。实际上,发生冲突之后的读游标采用的行为是:根据最新表数据重新计算结果集并维持当前行集的起始位置。 如果当前行已删除,则游标将进至下一行。
以下示例演示使用 CLP 的可滚动游标的实例。假定表 T 有六行:
create table T (a int, b int) create index idx1 on T(a) insert into T values (1, 1) insert into T values (2, 2) insert into T values (3, 1) insert into T values (3, 2) insert into T values (3, 3) insert into T values (4, 4)
一般来说,可以考虑这样一个示例:应用程序有两个语句句柄,一个用于读取,而另一个用于删除。
Statement handle 1: enable scrollable cursor; Statement handle 1: execute "SELECT A FROM T WHERE a < 10" Statement handle 2: prepare "DELETE FROM T WHERE a = ?" Statement handle 1: fetchscroll with SQL_FETCH_FIRST -- get (1, 1) Statement handle 1: fetchscroll with SQL_FETCH_NEXT -- get (2, 2) Statement handle 1: fetchscroll with SQL_FETCH_NEXT -- get (3, 1) Statement handle 2: execute --- suppose delete row (2, 2) Statement handle 1: fetchscroll with SQL_FETCH_NEXT -- re-compute previous rows, and return (3, 2) Statement handle 1: fetchscroll with SQL_FETCH_PRIOR -- get (3, 1) Statement handle 1: fetchscroll with SQL_FETCH_PRIOR -- get (1, 1) note that (2, 2) is gone Statement handle 1: fetchscroll with SQL_FETCH_ABSOLUTE, offset 2 -- get (3, 1) note that (2, 2) is gone Statement handle 1: fetchscroll with SQL_FETCH_ABSOLUTE, offset 5 -- get (4, 4)
落实和回滚下的游标,包括自动落实方式
不管是事务或是自动落实方式,打开的游标在落实期间将保持打开状态,而在回滚时关闭。
对象相关性
通过语句句柄 H 准备 SQL 语句可能会对特定对象设置某些相关性。例如,通过索引 Idx 从表 T 选择行需要表 T 和索引 Idx 的存在。如果这些对象被另一语句句柄删除(例如,如果索引 Idx 被删除),通过 H 重新执行该语句将强制重新编译 SQL 语句。因此,查询方案可能不同或者可能返回错误。