您的位置:程序门 -> oracle -> 高级技术



oracle 高手来看看这个死锁问题。(多线程往数据库中查询id,如果查询不到根据输入创建一条记录,并返回对应id)


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


oracle 高手来看看这个死锁问题。(多线程往数据库中查询id,如果查询不到根据输入创建一条记录,并返回对应id)[已结贴,结贴人:renfengxing]
发表于:2007-11-23 22:31:25 楼主
新手,第一次接触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);   --见存储过程2

end;
存储过程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.请问出了什么问题?哪里锁住了?
发表于:2007-11-23 22:36:001楼 得分:100
我感觉没说清楚,

你告诉我你在哪个会话(客户端)执行的?

以什么顺序执行的?
发表于:2007-11-24 00:16:292楼 得分:0
哦,我明白你的意思了.

我问一下你.你这里的表结构是怎么样的?

有unique   constraint   or   index?
因为你的并发很高,表除了这些insert还有其他的吗?

另外,请把你的00060生成的trace文件帖出来.

发表于:2007-11-24 00:17:103楼 得分:0
当然,把数据库版本要说出来.
发表于:2007-11-24 00:20:414楼 得分:0
也可以参考这个帖子的回复:

http://topic.csdn.net/u/20070719/09/13f24bd3-5fc4-43dc-b1e4-5475718031b4.html
发表于:2007-11-24 00:59:465楼 得分:0
oracle版本:10g
数据库两个字段:id,str,都是unique

发帖子的时候感觉:批量处理的时候,某些insert还没有及时提交,是否在insert的时候commit一下呢?
如果在insert的时候commit,是不是把其它操作也提交了呢?这样是不是没法实现批量处理了?
发表于:2007-11-25 09:46:186楼 得分:0
这个时候oracle会作这个校验的.

例如:
这样的情况:

session   1:

insert   into   aa   values(10,'y');==> 这里未提交也未回滚


session2:

insert   into   aa   values(10,'y');

在这里是会出现等待的,如果session1回滚,那么session2会执行成功,
如果session1提交,那么session2会报违反唯一性约束的错误,如果session1不提交也不回滚,那session2就一直在那儿等待,   等待的事件为enqueue.

发表于:2007-11-25 13:12:287楼 得分:0
出现这种情况该怎么解决?

能在insert   info之后加上commit吗?如果加了的话,是否会影响其它的操作也提交了?
发表于:2007-11-25 13:14:398楼 得分:0
我觉得oracle称:高并发,应该有它的理由,象我这种情况,显然没法并发,问题应该出在:我解决问题的方法可能和普通的方法不同,我用的方法不正统,
那么:象我这种问题,正统的解决办法是怎样呢?
发表于:2007-11-25 17:51:409楼 得分:0
能把表结构信息列一下吗?

你的unique是什么情况?

我感觉有些问题.是分别的unique   constraint?
还是组合的?
发表于:2007-11-25 18:10:3510楼 得分:0
需求不够清晰
假设   id       是主键,它的值一定来自序列s_str_id,那么无论有多少个并发事务,每个事务获取到的id都是唯一的,根本没有校验的必要;
如果你能保证id唯一来源于序列s_str_id,可以尝试将序列catch size设为0,将表上的约束删除(序列是唯一的,约束验证除了增加资源消耗外没任何好处)

假设你的id不是主键,值来源也不唯一,那么就需要综合考虑它的其他关联sql和关联操作,仔细分析是否关联操作和验证操作产生冲突造成了死锁
发表于:2007-11-25 23:15:5611楼 得分:0
我验证的不是id,而是str,因为str也需要唯一

根据楼上adaizi1980的说法,不知道是不是这个意思:
只有id是sequeue产生的,将cache   size设为0,那么就不需要验证str是否唯一了?
发表于:2007-11-27 23:28:4312楼 得分:0
所以你就创建了两个约一的约束?是不是?

发表于:2007-11-27 23:32:0613楼 得分:0
对于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文件帖上来.
发表于:2007-11-27 23:56:1814楼 得分:0
是哪个表被锁?


快速检索

最新资讯
热门点击