閱讀180 返回首頁    go 阿裏雲 go 技術社區[雲棲]


深入內核:Oracle數據提交與事務隔離的深度解析

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

崔華,網名 dbsnake

Oracle ACE Director,ACOUG 核心專家

編輯手記:感謝崔華授權我們獨家轉載其精品文章,也歡迎大家向“Oracle”社區投稿。

大家都知道的一個常識是 - Oracle 裏未 commit 的數據除了當前 session 之外,其他 session 是看不到的


我這裏演示了一個有趣的例子,在這個例子裏我們可以看到,Oracle裏未成功 commit 的數據我們也可能能看到

我同時啟4個 session。

 

先在 session 1裏創建一個表t1,插入一條數據但不 commit:

Session 1:

Connected to Oracle Database 11g

 Enterprise Edition Release 11.2.0.1.0

Connected as scott

SQL> create table t1(id number, name varchar2(10));

Table created

 

SQL> insert into t1 values(1,’CUIHUA’);

1 row inserted

 

SQL> select * from t1;

        ID NAME

———- ———-

         1 CUIHUA

 

此時跳到 session 2,因session 1裏剛插入的那條數據還未commit,所以這個時候 session 2是看不到這條數據的:

Session 2:

SQL> select * from t1;

 

        ID NAME

———- ———-

 

接著我們跳到 session 3,把lgwr進程suspend住:

Session 3:

SQL> select spid from v$process where pname=’LGWR’;

 

SPID

————————

2316

 

SQL> oradebug setospid 2316

Oracle pid: 11, Windows thread id: 2316,

 image: ORACLE.EXE (LGWR)

SQL> oradebug suspend

已處理的語句

 

現在我們回到 session 1,執行commit命令,因為 lgwr 進程已經被我們 suspend 住了,所以當前 session 1裏要執行的 commit 操作一定會被hang住:

Session1:

SQL> commit;

……這裏 hang 住了

 

Oracle 裏 commit 操作的流程是這樣的:

1、Oracle 先去改這個 transaction 所對應的 undo segment header 中 slot 的狀態;

2、改完狀態後再 flush log buffer;


現在我們把lgwr hold住了,所以上述步驟2 Oracle是沒法做了,但步驟1還是可以做的。

而隻要步驟1做完了,其他的 session 就能看到這個transaction所做的改變了(通過ITL中記錄的 transaction id 去 check相應的 undo segment header 中 slot 的狀態),也就是說對於其他 session 而言,這個 transaction 已經 commit 了,雖然這個 transaction 其實並沒有成功commit。

 

好了,我們現在回到session 2,看一下我們現在能否看到剛才insert的那條記錄:

Session 2:

SQL> select * from t1;

        ID NAME

———- ———-

         1 CUIHUA

 

從結果裏可以看到,剛才看不到的那條記錄現在我們已經能看到了,即 session 1對於 session2而言已經 commit 了,雖然 session1的 commit 操作其實並沒有成功的做完。

 

現在我們跳到 session 4,執行shutdown abort:

Session 4:

SQL> shutdown abort

ORACLE 例程已經關閉。

 

然後我們再在 session 4中執行 startup,startup 後我們從 alert log 裏可以很明顯的看到 

Oracle做了 instance recovery:

640?wx_fmt=png&wxfrom=5&wx_lazy=1

 

等待上述庫成功startup後,我們再次回到session 1,看一下剛才我們已經commit的那條數據是否還在:

Session 1:

SQL> select * from t1;

 

        ID NAME

———- ———-

 

從結果裏可以看到,剛才我們 insert 且執行了 commit 操作的那條記錄現在已經丟失了。


建議大家動手操作一下,以深入理解Oracle的事務隔離機製,事務恢複原理。


本文出自數據和雲公眾號,原文鏈接


最後更新:2017-07-17 18:04:07

  上一篇:go  深入內核:Oracle數據庫裏SELECT操作Hang解析
  下一篇:go  深入內核:從Oracle ASM自動備份頭塊到ASMFD