日期:2014-05-17  浏览次数:21000 次

(急)求助,CICS程序中,Oracle怎样避免插入重复的记录!!!!
情况是这样的:这个表的KEY是这样的ACNO+DATE+SEQ,每天对于每个ACNO可能会有多个操作,那么每一次的操作就会写一天(ACNO+DATE+SEQ)的记录,这样SEQ就需要时逐个增加的,但是现在考虑到多个程序都可能同时写入SEQ相同的记录,那么后插入的程序就会报错,因为重复键值出现了!!请问各位如何避免这种情况出现呢?





------解决方案--------------------
用sequence序列代替
------解决方案--------------------
用序列当主键
每天更新一次seq字段,使用分析函数row_number,按序列值排序
------解决方案--------------------
建一个采番表
字段:ACNO,DATE,SEQ
每次取最大值,然后加1
做成共通,使用自制事务
每天删除前一天的数据
功能类似每一个账号对应一个序列
------解决方案--------------------
这属于多个临界资源的提取问题了,如果在应用系统非集群的情况下,我会放弃在ORACLE内部去完成,选择其它的做法:

我建议在程序的内存中去完成这部分操作,如果是JAVA我会这样去做:
1、将ACNO+DATE+当前最大值 ,在内存中使用键值对存放。
2、对于当前最大值使用对象Integer进行管理,判定和叠加过程都必须进行同步(只对这个计数器同步,不会整个内存字典同步,这样粒度很小),每次获取增加1,或者定位为JAVA中的易失变量,其在赋值过程中可以保证其安全性,不会导致两个线程获取到一个编号。
3、当发现ACNO存在但日期和当前日期不一致,将日期更改为系统日期,并修改当前最大值修改为1。
4、ACNO和DATE初始化就将其当前值装载进去。
5、如果出现新的ACNO那么内存找不到,再临时生成,这样只会生成一次,也不会影响运行速度。


如果要在ORACLE内部去完成:
在ORACLE内部定义一个CACHE表,其实和在程序中做差不多,只是在ORACLE内部定义了一个缓存表而已(表的属性增加一个catch即可,如果你的ACNO很多就直接用物理表吧),建立字段:
1、ACNO DATE 当前最大值
2、每次提取当前最大值,使用FOR UPDATE WAIT 1;--每个线程最多等待1秒,自己可以调整一下。
3、相当于自己做的序列,取出来后,记得回写增加1然后回写回去。
4、如果发现没有的ACNO就将它写进去,由一个过程在第一次启动数据库时,就调用一个初始化过程将这个缓存表写好。
5、如果发现ACNO存在,但日期和当前系统日期不一致,就将日期改为当前系统日期,并修改当前最大值修改为1;