oracle多线程死锁问题,散分~~~~~~~~
程序流程描述如下:
1.程序初始化时建立连接,进入主线程2;
2.主线程:
等待信号量event1(锁定数据库连接);
选择一条符合条件的记录idn;
如果idn不存在,则设置信号量event1(解除数据库连接锁定),并退出主线程,顺序执行到4;
用update把记录idn作已选择标记;
设置信号量event1(解除数据库连接锁定);
创建子线程3,带入的结构参数值为idn,子线程数加一(采用锁定加一法);
4.等待所有子线程结束;
断开数据库连接;
程序正常退出;
3.子线程:(入口结构参数为idn)
等待信号量event1;
锁定数据库连接;
选择idn记录的相关信息,并保存在变量中;
解除数据库连接锁定;
设置信号量event1;
打印idn记录的相关信息;
子线程数减一(采用锁定减一法)
如果子线程数为零,则设置所有子线程结束信号量;
结束子线程;
问题描述如下:
如果把3.子线程中的数据库操作部分去掉,而直接打印idn值,则程序可以从主线程成功创建子线程,并且所有的线程(主线程、子线程)都能正常结束;但如果加入了数据库操作的部分,则主线程在他建了约三百个子线程后就一直处于等待状态(不再创建子线程),看样子好像是死锁了;
在3.子线程中,打印函数是用互斥信号来控制打印的开始与结束的,因此系统在这里也有可能发生死锁;
csdn最高只允许本人出300分,想要分的可以另外想办法送,帮本人把这个死锁(或其它解决办法)找出来,就可以拿到分了。
本程序调试环境:P4(1.4) + 1G + win2ksp2 + o9i + pro c++ + vc6.0,有请在多线程数据库操作有丰富经验的高手指教,谢谢~~~~~
问题点数:300、回复次数:36Top
1 楼superrg(秀华)回复于 2002-01-11 11:16:23 得分 0
惨了,怎么我的贴子没有人回也没有人看呀???高手在哪里呀,高手在哪里????Top
2 楼superjj2002(小鸟)回复于 2002-01-11 12:30:45 得分 20
帮你抬一下,:)Top
3 楼flowerofwind(现实很残酷)回复于 2002-01-11 12:41:55 得分 20
你们俩的名字还有点相似哦Top
4 楼flowerofwind(现实很残酷)回复于 2002-01-11 12:43:44 得分 50
子线程中的数据库操作部分去掉,而直接打印idn值,则程序可以从主线程成功创建子线程,并且所有的线程(主线程、子线程)都能正常结束;但如果加入了数据库操作的部分,则主线程在他建了约三百个子线程后就一直处于等待状态(不再创建子线程),
这时候数据库操作有没有返回什么错误代码?Top
5 楼superrg(秀华)回复于 2002-01-11 12:49:07 得分 0
to superjj2002():
thanks...
to flowerofwind(现实很残酷):
由于屏幕打印太快了,没有看清有没有错误,难道如果有错误,程序就会一直等待吗???
我在程序中设置了oracle错误处理程序的呀~~~~~~~
Top
6 楼KingSunSha(弱水三千)回复于 2002-01-11 13:14:46 得分 0
把执行结果SPOOL去一个文件跟踪吧,这样查起来方便一点Top
7 楼superrg(秀华)回复于 2002-01-11 13:30:50 得分 0
to KingSunSha(弱水三千):
把所有的结果都放入spool文件中吗??成千上万个线程的结果,到时候怎么看好呢????Top
8 楼KingSunSha(弱水三千)回复于 2002-01-11 14:05:25 得分 0
当然不可能跟踪所有的信息,在程序执行的关键点和EXCEPTION上加入OUTPUT,或者逐步的加入,用排除法逐步缩小错误的范围。
大概也只能这样了Top
9 楼superrg(秀华)回复于 2002-01-11 14:55:02 得分 0
to KingSunSha(弱水三千):
但是所有子线程的程序都是一样的呀,我也不知道到时候是锁死在子线程还是在主线程呀,如果不是全加,跟没有加是一样的呀~~~~~Top
10 楼cmszzx()回复于 2002-01-11 15:53:45 得分 20
帮你推一推Top
11 楼KingSunSha(弱水三千)回复于 2002-01-11 16:12:17 得分 0
有难度,让我想一想Top
12 楼aimi0123456(艾米)回复于 2002-01-11 16:17:37 得分 20
真的能散到分?爽!Top
13 楼Haiwer(海阔天空)回复于 2002-01-11 16:24:03 得分 20
三千兄在想了,看来能解决!
我是来学习的!
Top
14 楼mycode(不写代码)回复于 2002-01-11 17:18:29 得分 20
你对数据库的操作是通过几个Connection来实现的.
Connection是一直存在还是即用即建.
个人觉得,访问数据库的操作,还是通过中间件服务器,如MTS或Tuxedo去实现.会较大的提高系统的稳定性.
Top
15 楼superrg(秀华)回复于 2002-01-11 17:35:24 得分 0
to mycode(不写代码):
只用了一个connection,用event1信号量控制数据库操作的,但是用中间件去实现的速度明显慢得多了~~~~~~
to KingSunSha(弱水三千):
赁你多年的数据库经验,究竟是什么原因锁住了???
to others:
Thanks a lot...
Top
16 楼mycode(不写代码)回复于 2002-01-11 17:45:34 得分 30
用update把记录idn作已选择标记;
为什么要这样用?
有没有可能是你的其他程序锁住了某条记录,导致你的程序遇上这条记录时,死锁,并且刚好出现在大约300条记录上.
出现死锁时,检查一下此时的数据库,是否出现死锁,以确定是否是数据库的操作出现死锁.
应用程序本身的结构,是否没有什么问题.
Top
17 楼superrg(秀华)回复于 2002-01-11 17:53:28 得分 0
to mycode(不写代码):
用update把记录idn作已选择标记的原因是:每个线程只处理一条记录,相当于游标的作用,如果不作标记,则下一次主线程产生子线程时就会重复地选择这一条记录了;而不使用游标的原因是因为整个表的数据都是动态的,子线程处理后有可能往这个表中加入新的数据;程序测试时只有我一个人在用这个测试库,如果说其它程序锁住了某条记录,则只能说是oracle系统锁住了,至于锁的原因,我就找不出来了~~~~~~晚上我再打开管理器看看有没有锁,如果没有锁就更难调了~~~~Top
18 楼KingSunSha(弱水三千)回复于 2002-01-11 18:06:10 得分 100
刚学了一些java中线程的运行原理,说实话不是很清楚。
记得书上讲到最容易发生死锁的情况是这样的:
session1 update(or lock) table1;
session2 update(or lock) table1;
session2 update(or lock) table2;
session1 update(or lock) table2;
session1.commit
session2.commit
这种情况下两个session相互等待对方commit完成,形成死锁。
但是你的情况好像不一样,因为用的是同一个connection。
在死锁发生的时候,你去查一下是不是有v$lock,看看能不能找到一点线索。
Top
19 楼superrg(秀华)回复于 2002-01-11 19:41:30 得分 0
KingSunSha(弱水三千):
怎么查v$lock呢?现在我在设打印断点,结果出来一大堆等待信号,也不知道哪一个是最后一个了~~~~~~~Top
20 楼superrg(秀华)回复于 2002-01-11 19:53:57 得分 0
我用OEM查,结果发现有九个会话,其中6个是后台的,一个是调试程序的,一个是sql plus的,另外一个是OEM进入时用的,而总共有十个锁,在两个后台会话中的,其中sid为2的会话有九个锁,锁类型都是MR型,占用的模式为share,资源id1为1-8 、201,资源id2都为0;而sid为3的会话有一个锁,类型为RT,占用模式为独占,资源id1为1,资源id2为0,是什么原因呢???三千,快来救命~~~~~~Top
21 楼grit(东东)回复于 2002-01-11 20:41:00 得分 0
因为主线程和子线程都是等待一个信号量(event1),因此操作是线性的,应该不会锁,
除非操作数据库的线程发生异常,不释放信号量。
打印需要这么多线程吗?如果都是等一台打印机,那打印还是线性的。是不是记录是变动的
,那可以一个线程处理记录,一个打印。
Top
22 楼superrg(秀华)回复于 2002-01-11 21:19:58 得分 0
to grit(东东):
我所指的打印是指把信息从屏幕上显示出来,显示不是最终的目的~~~~Top
23 楼KingSunSha(弱水三千)回复于 2002-01-11 21:30:08 得分 0
查v$lock很容易,用select * from v$lock;就可以
只是你的问题确实比较奇怪Top
24 楼superrg(秀华)回复于 2002-01-11 21:45:54 得分 0
to KingSunSha(弱水三千):
哦???那你看我刚才列出的锁是否正常呢??? Top
25 楼superrg(秀华)回复于 2002-01-11 22:14:40 得分 0
实际上跟我刚才列的是一样的~~~~
SQL> select * from v$lock;
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
CTIME BLOCK
---------- ----------
7AE531FC 7AE5320C 2 MR 201 0 4 0
11685 0
7AE531B0 7AE531C0 2 MR 8 0 4 0
11685 0
7AE53164 7AE53174 2 MR 7 0 4 0
11685 0
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
CTIME BLOCK
---------- ----------
7AE53118 7AE53128 2 MR 6 0 4 0
11685 0
7AE530CC 7AE530DC 2 MR 5 0 4 0
11685 0
7AE53080 7AE53090 2 MR 4 0 4 0
11685 0
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
CTIME BLOCK
---------- ----------
7AE53034 7AE53044 2 MR 3 0 4 0
11685 0
7AE52FE8 7AE52FF8 2 MR 2 0 4 0
11685 0
7AE52F9C 7AE52FAC 2 MR 1 0 4 0
11685 0
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
CTIME BLOCK
---------- ----------
7AE52EB8 7AE52EC8 3 RT 1 0 6 0
11688 0
已选择10行。Top
26 楼superrg(秀华)回复于 2002-01-11 22:26:32 得分 0
三千,我把程序退出后里面还是有十个锁,可见我程序的运行好像跟锁的产生无关呀~~~~~怪怪怪~~~~~你能不能看看你的数据库初始化时都有些什么锁呀??Top
27 楼cmszzx()回复于 2002-01-11 22:48:56 得分 0
还没有搞掂吗?再帮你推推Top
28 楼superrg(秀华)回复于 2002-01-11 23:22:13 得分 0
终于搞掂了,谢谢大家的帮忙,散分罗~~~~~~~Top
29 楼KingSunSha(弱水三千)回复于 2002-01-11 23:31:31 得分 0
我的库打开以后有8个lock,类型是MR/RT,每个update语句产生两个locks,类型为TX/TM,在v$locked_object中看到每个被update语句产生一个locked_object,同时可以看到其他的一些信息,
SQL> select * from v$locked_object
XIDUSN XIDSLOT XIDSQN OBJECT_ID SESSION_ID
---------- ---------- ---------- ---------- ----------
ORACLE_USERNAME OS_USER_NAME PROCESS
------------------------------ ------------------------------ ---------
LOCKED_MODE
-----------
5 45 50 4500 7
KNUT Administrator 4752:4680
3
还是不明白你的问题在哪里Top
30 楼KingSunSha(弱水三千)回复于 2002-01-11 23:33:19 得分 0
好像可以认为你的问题不在数据库端、、、、、、Top
31 楼KingSunSha(弱水三千)回复于 2002-01-11 23:34:58 得分 0
到底是什么问题?能分享一下经验吗?
我出300分,好不好?Top
32 楼superrg(秀华)回复于 2002-01-11 23:56:50 得分 0
to KingSunSha(弱水三千):
谢谢你的分了,问题的确出在数据库端,我现在还正在调,因为新的锁出现了,你帮了我这么多次,我不好意思要你的分,回头给你解释我所谓的死锁,One moment, pls....Top
33 楼superrg(秀华)回复于 2002-01-12 00:08:05 得分 0
to KingSunSha(弱水三千):
这一回不知道是哪里死锁了,更惨,先说说上面的问题,原记录数共有一万三千多条,其中有二十多条根据规则设定为废弃数据,昨天晚上我在update标记时忘了加条件,结果把这些记录都算进了正规数据中,结果当处理到这些记录里,程序一直处于等待状态,而oracle据我所知是不能直接设定操作超时的,所谓的死锁就是这样产生的;而我重新发现这个错误也算比较庆幸,办法是:把子线程总数减少到只允许一个子线程运行,结果每一次程序运行到第284条就停下来等待,于是我就查第285条记录,发现原来是一条早已废弃的数据,才猛然想起我犯的这个错。依三千你看,这是不是数据库的问题呢??只是不是数据库死锁的问题罢了,谢谢你,三千~~~~~~~Top
34 楼KingSunSha(弱水三千)回复于 2002-01-13 01:11:17 得分 0
是不是你的sql中对废弃的纪录有什么特殊的处理啊?废弃的纪录一般是在某个标记字段做了废弃的标记,对数据库操作本身不会有什么影响吧?
你把代码贴出来看看吧Top
35 楼SeaBig(海纳百川)回复于 2002-01-29 13:24:04 得分 0
关注!Top
36 楼wylyf(李寻欢)回复于 2002-01-31 13:42:57 得分 0
学习!Top




