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;
这里资源被咬住了好像。。在这报死锁了。。
删除数据后,再对表进行操作,出现了死锁。。
答案:2 悬赏:50 手机版
解决时间 2021-03-07 23:09
- 提问者网友:做自己de王妃
- 2021-03-07 17:36
最佳答案
- 五星知识达人网友:三千妖杀
- 2021-03-07 18:21
呵呵,锁的问题确实是让人头疼,我也是经常遇到,因为平时总涉及比较复杂的业务,所以经常对某一个表不停的操作,经常出现这倒霉的死锁。
试试把DELETE删除操作放后边,中间处理的时候,滤掉这个要删除的数据吧
呵呵,先无耻的回答一个。
试试把DELETE删除操作放后边,中间处理的时候,滤掉这个要删除的数据吧
呵呵,先无耻的回答一个。
全部回答
- 1楼网友:纵马山川剑自提
- 2021-03-07 19:01
当系统使用频繁就会出现插入操作和删除操作同时进行的情况。这个时候插入事务会先将主表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#
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯