今天看了tom大師關於sql restart的部落格,收益頗深。鑑於的繁瑣和以後查閱的方便,將主要內容總結至此。大家也可以通過如下位址檢視原博文及精彩點評(需要哦)。
大家都知道oracle通過一致性讀來防止阻塞並為查詢提供結果。但是對於寫或者說編輯操作,oracle是怎樣處理的那?例如下面的語句:
update t set x=2 where y=5;
對於這樣的語句,oracle首先會根據語句的執行起始時間t1和where條件進行基於t1的一致性查詢操作,找出y=5的所有記錄,然後對這些記錄進行更新操作。那麼這裡就存在乙個問題,假設在t2時間,oracle修改到記錄r,如果在t1和t2之間的時間段裡,某個使用者程序修改了記錄r並進行了提交,此時oracle會做如何處理那?我們知道,讀操作我們可以基於以往時間點構造一致性塊,但是對於寫操作,我們必須對當前塊進行操作。
首先我們在表tab上建立觸發器
sql> create or replace trigger tab_tri
2 before update on tab for each row
3 begin
4 dbms_output.put_line(' old.x = '||:old.x||',old.y ='||:old.y);
5 dbms_output.put_line(' new.x = '||:new.x||',new.y ='||:new.y);
6 end;
7 /
session1:更新某記錄,不提交
sql> update tab set x=2 where y=1;
session2:更新相同記錄,程序被阻塞
sql> update tab set x=3 where y=1;
session2:session1提交後
sql> update tab set x=3 where y=1;
old.x = 1,old.y =1
new.x = 3,new.y =1
old.x = 2,old.y =1
new.x = 3,new.y =1
已更新 1 行。
從這裡可以看出,如果更新r時,oracle發現r已經被修改過,那麼oracle會重新執行update語句。
下面讓我們修改一下觸發器
sql> create or replace trigger tab_tri
2 before update on tab for each row
3 begin
4 dbms_output.put_line('aaaaa');
5 end;
6 /
session2:在session1提交後:
sql> update tab set x=3 where y=1;
aaaaa
已更新 1 行。
非常奇怪?這裡update語句並沒有重新執行
下面在來改變一下執行語句:
sesion1:
sql> update tab set y=2 where y=1;
已更新 1 行。
session2:
sql> update tab set x=3 where y>0;
aaaaa
aaaaa
這裡update語句再次重新執行。好,我們總結如下:
如果在update(delete沒有測試,估計應該是相同的)語句的執行過程中,待操作記錄發生了改變,並且被改變的列在where子句或者row觸發器(after or before)的內部使用:old或者:new引用過,那麼update語句會將之前的操作回滾並重新執行。這也是after觸發器效率高於before觸發器的乙個原因,因為即便update重新執行,after觸發器只執行一次,而befer觸發器會執行兩次。如果發生了restart,oracle會在第二次執行的過程中嘗試使用select for update來進行操作,以避免發生再一次的restart。但是即便使用select for update ,依然有可能發生restart。
下面看一下restart產生的影響:
1:如果觸發器維護plsql中的全域性變數,那麼全域性變數可能是不準確的
2:任何utl_函式,例如utl_file, utl_http, utl_smtp,可能會執行兩次,因此這些函式時非事務性的,無法回滾
3:自治事務當然也會受影響而執行多次
語句 switch語句
switch語句的特點如下 1 switch x 被選擇的內容 即x 只能是byte,short,int,char這四種型別 2 備選答案並沒有指定的順序,但是執行肯定是從第乙個case開始的,如果其中有匹配的case,執行完,通過該case的break就結束了switch。如果沒有匹配的case,...
Python while語句,for語句
usr bin python coding utf 8 filename whiletest.py num 23running true while running i int raw input input a number if i num print right running false e...
迴圈for語句 if語句
if語句 if 表示式 else if 表示式 for迴圈 for var i 0 i 10 i if語句 if 表示式 else if 表示式 for迴圈 for var i 0 i 10 i while迴圈 while 表示式 使用場景 for 次數確定的時候使用 while 直到滿足摸個條件的...