新手,第一次接触oracle,第一次写存储过程
TableName:strtable
field1:id(自增号)
field2:str
数据量:非常庞大,不能所表
线程个数:300左右(多台机器)执行X存储过程:下面为一部分代码(X存储过程不需要返回)存储过程1:
create or replace procedure PROC_GAIN_STR_ID(
       instr in varchar2,
       outid out number
)
is
begin
--查询是否存在
     select id into outid from strtable where str = instr and rownum = 1;
     exception WHEN NO_DATA_FOUND THEN
      --不存在的话,增加一个,并返回outid
          PROC_APPEND_STR_RECORD(instr, outid); --见存储过程2END;
存储过程2:
create or replace procedure PROC_APPEND_STR_RECORD(
       instr in varchar2,
       outid out number
)
is
begin
--获取一个id
    select S_STR_ID.nextval into outid from dual;
    
    --插入
    insert into strtable(id, str) values(outid, instr);
    exception when DUP_VAL_ON_INDEX then
    --已经有此记录(并发时PROC_GAIN_STR_ID,中的查询可能不准确),查询,输出id
              select id into outid from strtable where str = instr and rownum = 1;END;
JAVA提交数据方法
X存储过程不需要返回,故采取批量提交数据。即:批量执行X存储过程之后再commit();我的X存储过程里面,没有任何一句所表的过程,出现异常@死锁@,ORA-00060.请问出了什么问题?哪里锁住了?

解决方案 »

  1.   

    哦,我明白你的意思了.我问一下你.你这里的表结构是怎么样的?有unique constraint or index?
    因为你的并发很高,表除了这些insert还有其他的吗?另外,请把你的00060生成的trace文件帖出来.
      

  2.   

    也可以参考这个帖子的回复:http://topic.csdn.net/u/20070719/09/13F24BD3-5FC4-43DC-B1E4-5475718031B4.html
      

  3.   

    oracle版本:10g
    数据库两个字段:id,str,都是unique发帖子的时候感觉:批量处理的时候,某些insert还没有及时提交,是否在insert的时候commit一下呢?
    如果在insert的时候commit,是不是把其它操作也提交了呢?这样是不是没法实现批量处理了?
      

  4.   

    这个时候oracle会作这个校验的.例如:
    这样的情况:session 1:insert into aa values(10,'y');==>这里未提交也未回滚
    session2:insert into aa values(10,'y');在这里是会出现等待的,如果session1回滚,那么session2会执行成功,
    如果session1提交,那么session2会报违反唯一性约束的错误,如果session1不提交也不回滚,那session2就一直在那儿等待, 等待的事件为enqueue.
      

  5.   

    出现这种情况该怎么解决?能在insert info之后加上commit吗?如果加了的话,是否会影响其它的操作也提交了?
      

  6.   

    我觉得oracle称:高并发,应该有它的理由,象我这种情况,显然没法并发,问题应该出在:我解决问题的方法可能和普通的方法不同,我用的方法不正统,
    那么:象我这种问题,正统的解决办法是怎样呢?
      

  7.   

    能把表结构信息列一下吗?你的unique是什么情况?我感觉有些问题.是分别的unique constraint?
    还是组合的?
      

  8.   

    需求不够清晰
    假设 id   是主键,它的值一定来自序列S_STR_ID,那么无论有多少个并发事务,每个事务获取到的id都是唯一的,根本没有校验的必要;
    如果你能保证id唯一来源于序列S_STR_ID,可以尝试将序列catch size设为0,将表上的约束删除(序列是唯一的,约束验证除了增加资源消耗外没任何好处)假设你的id不是主键,值来源也不唯一,那么就需要综合考虑它的其他关联sql和关联操作,仔细分析是否关联操作和验证操作产生冲突造成了死锁
      

  9.   

    我验证的不是ID,而是str,因为str也需要唯一根据楼上adaizi1980的说法,不知道是不是这个意思:
    只有ID是sequeue产生的,将cache size设为0,那么就不需要验证str是否唯一了?
      

  10.   

    对于sequence来说,也就是你的第一个unique constraint,不会构成deadlock但是对于第二个unique constriant来说,也就是你的str, 很有可能有重复的内容.而这时候还仅仅是产生enqueue等于而已,而死锁构成的要求是: session 1锁A行.session2锁B行.然后session1再锁B行,
    session 2再锁A行.这时候oracle就会检测到deadlock发生了,并且会强行rollback
    其中的一个session.而你这里显然没有这个情况,那么就有可能是其他的情况,
    如itl也有可能产生deadlock.所以我要你把死锁生成的trace文件帖上来.