流配置异常(ORA-01403)的完整解决过(一):http://yangtingkun.itpub.net/post/468/102138
流配置异常(ORA-01403)的完整解决过(二): http://yangtingkun.itpub.net/post/468/103639
流配置异常(ORA-01403)的完整解决过(三):http://yangtingkun.itpub.net/post/468/106287
将一个事务中的所有SQL语句按照顺序写到MY_RECORDS表中,剩下的问题似乎就简单了。
通过调用下面的匿名块,就可以找到第一个引起ORA-1403错误的数据:
SQL> SET SERVEROUT ON
SQL> BEGIN
2 FOR I IN (SELECT ID, STATMENTS FROM MY_RECORDS ORDER BY ID) LOOP
3 EXECUTE IMMEDIATE I.STATMENTS;
4 IF SQL%ROWCOUNT = 0 THEN
5 DBMS_OUTPUT.PUT_LINE(I.ID);
6 ROLLBACK;
7 RETURN;
8 END IF;
9 END LOOP;
10 ROLLBACK;
11 END;
12 /
1
PL/SQL 过程已成功完成。
目前找到的第一个不匹配的数据就是这个事务的第一条记录,通过比较这条UPDATE语句中WHERE条件和数据库中存在的字段的值,就可以发现造成数据不一致的问题。
通过UPDATE语句,将数据库中的现有的数据的值进行更新,将其更新为LCR中得到的DML语句中WHERE条件后给出的值。这样,就可以保证Oracle在进行流的应用的时候不会报ORA-1043错误了。
将第一条不匹配数据更新后,再次执行这个过程,找到第二条不匹配的数据,按照同样的步骤处理,然后再次需要下一条,直到整个事务处理完成。
需要注意一点,由于所有的DML操作都是针对真实的数据,因此无论是在匿名块中还是在手工处理的时候一定要小心,DML操作后一概回滚,避免修改真正的数据。
在得到一个事务中所有不匹配记录的UPDATE语句后,可以执行这些UPDATE语句,然后调用Oracle提供的过程将错误事务再次执行。
SQL> BEGIN
2 DBMS_APPLY_ADM.EXECUTE_ERROR(
3 LOCAL_TRANSACTION_ID => '18.42.47210',
4 EXECUTE_AS_USER => FALSE);
5 END;
6 /
PL/SQL procedure successfully completed.
SQL> commit;
Commit complete.
到目前为止似乎仍然很顺利。但是马上又有新的问题了。
首先一个问题就是调用MY_PRINT_TRANSACTION过程时间太长,生成一个事务的18000多条的LCR居然需要3、4个小时。这个问题还没来得及解决,就出现了更加严重的问题。
IXDBA.NET社区论坛对于第一个事务,完全通过手工比对出不匹配的数据,幸运的是,第一个事务中,只找到5条不匹配的记录。
但是第二个事务中,通过手工的方式找了7、8个不匹配的数据,下一个出错的数据ID才到二十几,按照这个比率,18000多个SQL,需要找到不匹配的大概有几千,这个工作要是手工做不知道要花费多长的时间。
幸运的是,通过第一个事务的处理,已经当前事务中已经找到的不匹配的数据,发现了一个规律。几乎所有造成不匹配的数据都是一个最后修改日期发生了变化。
而且当前流应用站点对于的捕获站点只捕获了三张表的数据。因此可以尝试通过编写一个小的过程,自动获得改正不匹配的更新语句。
由于表的数量有限,且表名确定的话,需要更新的字段名称也确定下来,唯一定位一条记录的主键列也是可以确定的。而且,由于数据是因为不匹配造成的,我虽然很难清楚当前数据库中的值是多少,但是我只有根据LCR也就是MY_RECORDS中语句的WHERE条件中所带的值去更新,就可以解决不匹配的问题。而且,由于设置表级主键列的LOGGING,LCR中必然会包含主键列和相应的值。
根据上面这些条件,就可以编写出获取更新不匹配数据的UPDATE语句的匿名块了。
输入的SQL语句类型于:
UPDATE NDMAIN.ORD_ORDER SET RECEIVE_TOTAL = 9570.7, MODIFY_DATE = '2006-05-18 10:43:18' WHERE ORDER_ID = '2CA50BE524F7113713CD481D' and RECEIVE_TOTAL = 9570.7 and MODIFY_DATE = '2006-05-18 10:32:57'
而我需要得到的输出SQL语句类型于:
UPDATE NDMAIN.ORD_ORDER SET MODIFY_DATE = '2006-05-18 10:32:57' WHERE ORDER_ID = '2CA50BE524F7113713CD481D'