Re: locking question when using before update trigger
Date: 28 Jan 2003 13:22:47 -0800
Message-ID: <b16sb705iu_at_drn.newsguy.com>
In article <6opd3vk4bnu7l0vg2vi2mjur0rcd7j696i_at_4ax.com>, Tim says...
>
>I'm trying to understand a locking issue I'm having with my database.
>
>Scenario is as follows:
>
>1. I have a before update trigger on all of my tables to update a
>timestamp column (so I know the last time a row was updated). This
>column is never updated directly by any SQL. Trigger looks like the
>following:
>
>create or replace trigger im_ins_upd_table_a
>BEFORE INSERT OR UPDATE ON table_a
>FOR EACH ROW
>BEGIN
> if not ((:new.replicated_flag = 'Y') and (:old.replicated_flag =
>'N')) THEN
> :new.last_touch_date := sysdate;
> END IF;
>END;
>
>2. I have 2 tables, 1 is named table_a and the other table_b. table_b
>has a foreign key to table_a. I have made sure that ALL foreign key
>columns in my schema are indexed.
>
>When I do an update on table_a (any column other than last_touch_date)
>any future inserts into table_b are blocked until I commit/rollback
>the update on table_a (even though I haven't even updated the column
>that was the foreign key from table_b).
>
>If I disable the trigger I have no blocking issues.
>
>Any help would be greatly appreciated.
>
>Tim Callaghan
>
something else is amiss here -- something missing from the example. Can you
take my example and make it suffer from this problem:
ops$tkyte_at_ORA817DEV> create table table_a ( x int primary key, replicated_flag
char(1), last_touch_date date );
Table created.
ops$tkyte_at_ORA817DEV> create table table_b ( x references table_a );
Table created.
ops$tkyte_at_ORA817DEV> create index table_b_idx on table_b(x);
Index created.
ops$tkyte_at_ORA817DEV>
5 rows created.
ops$tkyte_at_ORA817DEV> commit;
Commit complete.
ops$tkyte_at_ORA817DEV>
ops$tkyte_at_ORA817DEV> insert into table_a select rownum, 'X', sysdate from
all_users where rownum <= 5;
ops$tkyte_at_ORA817DEV> create or replace trigger im_ins_upd_table_a
2 BEFORE INSERT OR UPDATE ON table_a
4 BEGIN
5 if not ((:new.replicated_flag = 'Y') and (:old.replicated_flag = 'N'))
6 THEN
7 dbms_output.put_line( 'touching ' || :new.x ); 8 :new.last_touch_date := sysdate;9 END IF;
10 END;
11 /
Trigger created.
ops$tkyte_at_ORA817DEV> ops$tkyte_at_ORA817DEV> ops$tkyte_at_ORA817DEV> update table_a set x=x where rownum = 1;touching 1
1 row updated.
ops$tkyte_at_ORA817DEV>
ops$tkyte_at_ORA817DEV> declare
2 pragma autonomous_transaction;
3 begin
4 insert into table_b values ( 3 ); 5 commit;
6 end;
7 /
PL/SQL procedure successfully completed.
ops$tkyte_at_ORA817DEV>
ops$tkyte_at_ORA817DEV> lock table table_b in exclusive mode;
Table(s) Locked.
ops$tkyte_at_ORA817DEV>
ops$tkyte_at_ORA817DEV> declare
2 pragma autonomous_transaction;
3 begin
4 insert into table_b values ( 3 ); 5 commit;
6 end;
7 /
declare
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource ORA-06512: at line 4
I did the last part to show that if TABLE_B where locked -- the autonomous transaction would in fact be blocked. No matter what I do -- table_b is modifiable unless I lock it.
So, can you flesh out the example a bit more?
-- Thomas Kyte (tkyte_at_oracle.com) http://asktom.oracle.com/ Expert one on one Oracle, programming techniques and solutions for Oracle. http://www.amazon.com/exec/obidos/ASIN/1861004826/ Opinions are mine and do not necessarily reflect those of Oracle CorpReceived on Tue Jan 28 2003 - 22:22:47 CET