问题描述

在datastage8.7版本中使用db2 connector往表中写入数据,Table action选择Truncate,同时在before sql中使用sql语句,对另一只表做DML操作;如果DML语句报错时,此时清空表的操作会异常中断,导致目标表出现SQLCODE=-1477,SQLSTATE=55019的错误,此时只能drop表后重建

测试流程如下:

新建两张测试表,并插入测试数据

create table TMP_20181120(id integer not null,primary key (id));
insert into TMP_20181120 values(1);
insert into TMP_20181120 values(2);

create table TMP_20181120_2(id integer not null,primary key (id));
insert into TMP_20181120 values(1);
insert into TMP_20181120 values(2);

开发一个简单的测试作业

在datastage8.7版本使用truncate清空表,同时使用before语句时的坑_主键

在datastage8.7版本使用truncate清空表,同时使用before语句时的坑_回滚_02
 

Table name:TMP_20181120_2

Table action:Truncate

Generate truncate statement at runtime:YES

Befor SQL:update TMP_20181120 set id=2 where id=1

 

Befor SQL的语句会导致主键冲突,导致程序报错

运行程序,得到日志如下:

在datastage8.7版本使用truncate清空表,同时使用before语句时的坑_回滚_03

从日志里可看到Truncate成功,before sql报主键冲突;但是此时查询TMP_20181120会发现如下报错

在datastage8.7版本使用truncate清空表,同时使用before语句时的坑_回滚_04

For table TMP_20181120_2 an object "xxx" in table splace "x" can not beaccessed .. SQLCODE=-1477 ,SQLSTATE=55019

问题分析:

从ds日志可以看到,ds执行时先执行以下语句对TMP_20181120_2进行清空

ALTER TABLE TMP_20181120_2 ACTIVATE NOT LOGGED WITH EMPTY TABLE

此时日志提示成功,接着执行before sql

update TMP_20181120 set id=2 where id=1

此时报主键冲突,整个程序中止;

查询55019的报错原因

SQL1477N  对于表 "<表名>",不能访问表空间 "<表空间标识>" 中的对象 "<对象标识>"。
说明:
试图访问一个表,而该表的其中一个对象是不可访问的。由于下列原因之一,该表可能不可访问:
1.当回滚工作单元时,该表激活了 NOT LOGGED INITIALLY。
2.该表是一个已创建的分区临时表或者已声明的分区临时表,由于已声明此临时表或者已将它实例化,因此一个或多个数据库分区失败。
3.ROLLFORWARD 在此表上遇到了 NOT LOGGED INITIALLY 激活,或者遇到了NONRECOVERABLE 装入。
不允许访问此表,因为不能保证其完整性。

开启了不记日志的操作之后,数据清空完成后此时事务未提交,当update执行失败后,发生回滚,导致TMP_20181120表不可用;此时只能drop表后重建;

 

处理方式:

在ds 11.5版本中未发现此问题

如果在8.7版本中使用trucate时,做如下操作

Generate truncate statement at runtime:NO
Truncate statement:TRUNCATE TABLE TMP_20181120_2 IMMEDIATE

在datastage8.7版本使用truncate清空表,同时使用before语句时的坑_sql_05

由于truncate自动提交,此时,beforesql报错也不会影响目标表了

在datastage8.7版本使用truncate清空表,同时使用before语句时的坑_回滚_06