永发信息网

删除数据后,再对表进行操作,出现了死锁。。

答案:2  悬赏:50  手机版
解决时间 2021-03-07 23:09
create or replace trigger change_total
after insert or delete on stock
for each row
declare
v_counter int;
v_numbers number(8);
v_disrupt number(3);
v_name total.name%type;
cursor name_cur
IS
select goods_name from stock
where basket_id=:old.basket_id;
PRAGMA AUTONOMOUS_TRANSACTION;
begin
case
when inserting then
select count(*) into v_counter from stock
where goods_name=:new.goods_name;
if v_counter <>0 then
select sum(numbers) into v_numbers from stock
where goods_name=:new.goods_name;
v_numbers:= v_numbers + :new.numbers;
update total set sum_total=v_numbers
where name=:new.goods_name;
select disrupt into v_disrupt from total
where name=:new.goods_name;
update total set disrupt=v_disrupt+1
where name=:new.goods_name;
if v_numbers>=15 and v_numbers<=50 then
update total set warn='正常'
where name=:new.goods_name;
end if;
if v_numbers<15 then
update total set warn='库存不足'
where name=:new.goods_name;
end if;
if v_numbers>50 then
update total set warn='库存过剩'
where name=:new.goods_name;
end if;
else
if :new.numbers>=15 and :new.numbers<=50 then
insert into total values(:new.goods_name,:new.numbers,'正常',1);
end if;
if :new.numbers<15 then
insert into total values(:new.goods_name,:new.numbers,'库存不足',1);
end if;
if :new.numbers>50 then
insert into total values(:new.goods_name,:new.numbers,'库存过剩',1);
end if;
end if;

when deleting then
delete from stock where basket_id=:old.basket_id;
open name_cur;
loop
fetch name_cur into v_name;
exit when name_cur%notfound;
select sum(numbers) into v_numbers from stock
where goods_name=v_name;

if v_numbers=0 then
delete from total where name=v_name;
else
update total set sum_total=v_numbers
where name=v_name;
select disrupt into v_disrupt from total
where name=v_name;
update total set disrupt=v_disrupt-1
where name=v_name;
if v_numbers>=15 and v_numbers<=50 then
update total set warn='正常'
where name=v_name;
end if;
if v_numbers<15 then
update total set warn='库存不足'
where name=v_name;
end if;
if v_numbers>50 then
update total set warn='库存过剩'
where name=v_name;
end if;
end if;
end loop;
close name_cur;
end case;
commit;
end change_total;
就在 when deleting then
delete from stock where basket_id=:old.basket_id;
这里资源被咬住了好像。。在这报死锁了。。
最佳答案
呵呵,锁的问题确实是让人头疼,我也是经常遇到,因为平时总涉及比较复杂的业务,所以经常对某一个表不停的操作,经常出现这倒霉的死锁。
试试把DELETE删除操作放后边,中间处理的时候,滤掉这个要删除的数据吧
呵呵,先无耻的回答一个。
全部回答
当系统使用频繁就会出现插入操作和删除操作同时进行的情况。这个时候插入事务会先将主表a放置独占锁,然后去访问子表b,而同时删除事务会对子表b放置独占锁,然后去访问主表a。插入事务会一直独占着a表,等待访问b表,删除事务也一直独占着b表等待访问a表,于是两个事务相互独占一个表,等待对方释放资源,这样就造成了死锁。 遇到这种情况我听说了二种做法:1 删除a表数据之前,先使用一个事务将b表中相关外键指向另外a表中的另外一个数据(比如在a表中专门建一行数据,主键设置为0,永远不会对这行数据执行删除操作),这样就消除了要被删除的数据在ab两个表中的关系。然后就可以使用删除事务,先删除a表中的数据,再删除b表中的数据,以达到和插入事务表访问一致,避免死锁。2 在外键关系中,将“删除规则”设置为“层叠”,这样删除事务只需要直接去删除主表a,而不需要对子表b进行操作。因为删除规则设置为层叠以后,删除主表中的数据,子表中所有外键关联的数据也同时删除了。以上二个解决办法 1 多了一次更新操作,2还可以 ,一般插入时不需要使用事务,删除时用cascade 插入时可能出现的数据不完整,在读取时作验证,不完整数据直接忽略,跑作业定期清理。因为无论插入时使用不使用事务,读取时都要作验证以确保数据正确性而不致程序出错,对应的定期数据清理也是必不可少的,所以并不会因为插入时不使用事务而造成过多的数据库访问。用方法2,并规范相关操作的调用,比如通过权限设定限定删除操作不会被随意执行,更大程度上避免误删。第2种做法是值得推荐的做法,虽然具有一定性能影响,但是从数据的一致性考虑,是最佳的。 察看死锁 select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode from v$locked_object lo, dba_objects ao, v$session sess where ao.object_id = lo.object_id and lo.session_id = sess.sid order by ao.object_name ; 清除死锁 alter system kill session sid,.serial#
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
佳木斯有几个篮球馆?
饭店除臭法
旺春微型车修理在哪里啊,我有事要去这个地方
【光谱分析法】光谱分析法通常可获得其他分析
摩根家族到底有多少钱?
怀孕期间能做瑜伽腹式呼吸么?
黑木耳特殊含义是指阴唇黑吗
佛教有那些流派?是哪八大宗?其来源?
惠州市购买社保金额多少
杨师傅韩式烤肉拌饭地址在哪,我要去那里办事
梦见敌人家缺少所需东西,寓意什么? 还有,
女孩名字大全属羊姓张带恩字
判断下列具有手性碳原子的分子是A.CH4 B.CH3C
为什么在微信上买高铁票没有发具体信息?
如何申请国家保密配方
推荐资讯
手表表盘会随着体温变颜色!以前小时候带过一
形容颜色的abab的词语
招牌动作是什么意思
衡山县衡阳衡山农商银行(城关支行)这个地址怎
求一个正交相似变换矩阵,使已知矩阵变为对角
我买的韩国三益二手钢琴发现旁边的木板不是原
法铃电动车质量怎么样?
金味正宗南京鸭血粉丝汤这个地址在什么地方,
悉尼大学 it 专业是不是很难
文山市文鸿投资有限责任公司怎么去啊,有知道
哪些动物的冬眠方式
从事新娘化妆盘头工作月薪多少
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?