批量文件处理中,如果因为某条数据错误导致了job abend,重新启动job再处理,几十分钟甚至几个小时的作业丢失对于分秒必争的batch cycle就是个噩梦!
尤其是对DB2和file同时处理的关键程序,job abend,DB2 roll back,但是VSAM file却是已写的已经写进去,已更新的已经更新,无法保持同步,再re-run,数据一片狼藉。
有一个很好的practice能够解决上述问题。注意,一下三部分是协同运作,从而保证DB2, VSAM, Sequential file保持同步。
1,DB2:
1)- 加入commit,比如每处理1000条数据,commit一次,这时要注意定义DB2 cursor的时候要用with hold,防止commit使把游标关掉。
2)- 在cobol中引入专门用来记录处理到多少条的DB2 table,暂且命名为record table。key值可以记录作业名,步骤名,程序名,条数。每次读入程序,先去检索record table是否有restart信息:
如果有,那么证明这个程序是异常终止掉重新启动的,那么就读文件,一直读到record table里记录的那一条,从下一条开始处理。这样,就跳过了已经处理过的数据,不做造成重复作业。
如果没有,我们需要在record table里插入数据,创造出这样的记录。
那么在程序正常处理后,每次commit之前,在record table里记下处理过的条数。
假设在任何时候出现了问题,DB2会roll back到之前commit的点,而不是全部回滚。
如果程序正常处理终了,那么只需delete掉record table里的数据,本次记录结束。
经常commit,还有一点好处,是避免大批量DB2数据pending的状态。大量数据等待,也会导致系统资源崩溃。
2, VSAM 文件:
在程序中可能会对VSAM文件进行write(insert),rewrite(update),delete的操作,而且这些操作是不可逆的,不会因为abend而进行任何回滚。
解决办法是记录每次VSAM的操作,记录下VSAM名字,操作,操作之前的数据,以及commit的记录。
如果有abend,需要把VSAM file的变化以commit为节点,全部撤回,insert的给delete掉,update的给update回去,delete掉的给insert回来。
着需要另外一个程序来完成。
3,Sequential 文件:
Sequential包括GDG文件和一些flat文件,这类文件的特点是只能逐条记录,并且不可逆,而且在作业中,这类文件的disposition属性为(New,Catalog,Delete)。重启作业新建文件,之前的记录就会丢失。
如果改成Mod或是share,那么重新启动作业,只会让文件里的记录重复(比如1000条的时候commit,1500条的时候abend,那么重启会从1001条开始,那么这时1001到1500之间写出的文件记录就会是重复的)。
一个解决办法是定义另一个Sequential 文件,暂且命名为memory file,记录每个Sequential 文件的记录,以及commit的点。
当主程序查询record table发现此时是个重启程序后,则执行去读memory file,把所有记录下来的记录全重新写一次,直到上次commit的节点。
整个过程仿佛比较庞杂,然而这是我们在处理批次程序中不得不考虑的事情,在JCL以及COBOL程序里的设置上,有很多细节需要注意。如果有问题或需要,请留言,我们进一步讨论。
希望能有朋友也来分享batch restart的方法,我们一起探讨进步。