新手,第一次接触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.请问出了什么问题?哪里锁住了?
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.请问出了什么问题?哪里锁住了?
因为你的并发很高,表除了这些insert还有其他的吗?另外,请把你的00060生成的trace文件帖出来.
数据库两个字段:id,str,都是unique发帖子的时候感觉:批量处理的时候,某些insert还没有及时提交,是否在insert的时候commit一下呢?
如果在insert的时候commit,是不是把其它操作也提交了呢?这样是不是没法实现批量处理了?
这样的情况:session 1:insert into aa values(10,'y');==>这里未提交也未回滚
session2:insert into aa values(10,'y');在这里是会出现等待的,如果session1回滚,那么session2会执行成功,
如果session1提交,那么session2会报违反唯一性约束的错误,如果session1不提交也不回滚,那session2就一直在那儿等待, 等待的事件为enqueue.
那么:象我这种问题,正统的解决办法是怎样呢?
还是组合的?
假设 id 是主键,它的值一定来自序列S_STR_ID,那么无论有多少个并发事务,每个事务获取到的id都是唯一的,根本没有校验的必要;
如果你能保证id唯一来源于序列S_STR_ID,可以尝试将序列catch size设为0,将表上的约束删除(序列是唯一的,约束验证除了增加资源消耗外没任何好处)假设你的id不是主键,值来源也不唯一,那么就需要综合考虑它的其他关联sql和关联操作,仔细分析是否关联操作和验证操作产生冲突造成了死锁
只有ID是sequeue产生的,将cache size设为0,那么就不需要验证str是否唯一了?
session 2再锁A行.这时候oracle就会检测到deadlock发生了,并且会强行rollback
其中的一个session.而你这里显然没有这个情况,那么就有可能是其他的情况,
如itl也有可能产生deadlock.所以我要你把死锁生成的trace文件帖上来.