会话 session 1:
SQL> select distinct sid from v$mystat;
SID
----------
145
SQL> create table t as select rownum id from dba_users;
表已创建。
若修改 id>10 的记录:
SQL> select * from t where id>10 for update;
ID
----------
11
12
13
14
15
16
17
18
19
20
21
ID
----------
22
23
24
25
26
27
28
29
30
31
32
ID
----------
33
34
35
36
37
已选择27行。
SQL>
打开会话 session 2:
SQL> select distinct sid from v$mystat;
SID
----------
142
SQL> select * from t where id>10 for update;
这时,session 2 就会被阻塞,因为 session 2 需要等待 session 1 的操作结果。
SQL> select sid,type,id1,id2,lmode,request,block
2 from v$lock where sid in (145,142)
3 order by sid;
SID TYPE ID1 ID2 LMODE REQUEST BLOCK
---------- ----- ---------- ---------- ---------- ---------- ----------
142 TX 327712 46191 0 6 0
142 TM 129305 0 3 0 0
142 AE 99 0 4 0 0
145 TX 327712 46191 6 0 1
145 TM 129305 0 3 0 0
145 TO 62986 1 3 0 0
145 AE 99 0 4 0 0
已选择7行。
SQL>
session 1 持有一个 lmode=6 的事务锁(TX),而 session 2 等待这个事务锁,block=1 表示当前会话阻塞了其他会话。
如果程序设置成这样,通常会保护 session 1 用户的数据,但是对于 session 2 用户来说,如果 session 1 迟迟不提交,将会一直等下去,对于用户来说,它很可能不知道发生了什么情况,也不知道要等待多长时间。
如果 session 2 不愿意等待,可以通过如下操作来获得一个错误通知而悟无需等待。
若会话 session 1:
SQL> select * from t where id>10 for update nowait;
ID
----------
11
12
13
14
15
16
17
18
19
20
21
ID
----------
22
23
24
25
26
27
28
29
30
31
32
ID
----------
33
34
35
36
37
已选择27行。
SQL>
在会话 session 2:
SQL> select * from t where id>10 for update nowait;
select * from t where id>10 for update nowait
*
第 1 行出现错误:
ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效
SQL>
通过使用 nowait 选项,可以让后续操作的用户不必等待而直接收到一个错误信息。在有人为干预的情况下,这种错误提示无疑会有助于故障的判断。
但对于一个自动运行的系统来说,等待,似乎更合理写,尽管要等待,但它能够保证系统正常运行而不会中断。