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

解决方案 »

  1.   

    序列解决不了这个问题,因为有很多账号(ACNO),如果用序列的话,那么每一个账号(ACNO)都需要一个序列。
      

  2.   

    一个序列只对应数据库表中的一个字段ACNO应该是一个字段吧
      

  3.   

    KEY有意义吗?他的唯一性,完全用序列来代替不要在乎它里面存储是ACNO+DATE+SEQ,还是普通的序列值
      

  4.   

    用序列当主键
    每天更新一次seq字段,使用分析函数row_number,按序列值排序
      

  5.   

    建一个采番表
    字段:ACNO,DATE,SEQ
    每次取最大值,然后加1
    做成共通,使用自制事务
    每天删除前一天的数据
    功能类似每一个账号对应一个序列
      

  6.   

    你每天都数据量有多大啊?使用序列+帐号+日期还可以重复?一个20位的SEQUENCE+8位DATE+帐号.
      

  7.   

    顶一下
         oracle QQ群:54775466
                    欢迎大家来一起探讨。
      

  8.   

    这属于多个临界资源的提取问题了,如果在应用系统非集群的情况下,我会放弃在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;