The five common DML statements that willblock in the database are INSERT, UPDATE,DELETE.MERGE and SELECT FOR UPDATE.
The solution to a blocked SELECT FOR UPDATEis trivial: simply add the NOWAIT clause and it will no longer block. Instead,your application will report back to the end user that the row is alreadylocked.
INSERTS的阻塞通常發生在允許終端用戶生成主鍵或者唯一性列值的時候,比較簡單的避免這種情況發生的辦法是用SEQUENCE來生成主鍵或者唯一性列值。如果不能使用SEQUENCE的話,可以使用手動的鎖,通過DBMS_LOCK包。
ORACLE有無限的ROW-LEVEL locking,但是有有限的enqueue locks.
要將執行DBMS_LOCK的權限賦給用戶(SCHEMA)
SQL> grant execute on dbms_lock to ops;
授權成功。
SQL> create or replace trigger demo_bifer
2 before insert on demo
3 for each row
4 declare
5 l_lock_id number;
6 resource_busy exception;
7 pragma exception_init( resource_busy,-54);
8 begin
9 l_lock_id :=
10 dbms_utility.get_hash_value (to_char( :new.x),0,1024);
11 if(dbms_lock.request
12 (id => l_lock_id,
13 lockmode=> dbms_lock.x_mode,
14 timeout => 0,
15 release_on_commit => TRUE) <> 0 )
16 then
17 raise resource_busy;
18 end if;
19 end;
20 /
觸發器已創建
在一個session下執行
SQL> insert into demo values (1);
已創建 1 行。
換另一個session下
SQL> insert into demo values (1);
insert into demo values (1)
*
ERROR 位於第 1 行:
ORA-00054: 資源正忙,要求指定 NOWAIT
ORA-06512: 在"OPS.DEMO_BIFER", line 14
ORA-04088: 觸發器 'OPS.DEMO_BIFER' 執行過程中出錯