深入內核:Oracle數據提交與事務隔離的深度解析
崔華,網名 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:
等待上述庫成功startup後,我們再次回到session 1,看一下剛才我們已經commit的那條數據是否還在:
Session 1:
SQL> select * from t1;
ID NAME
———- ———-
從結果裏可以看到,剛才我們 insert 且執行了 commit 操作的那條記錄現在已經丟失了。
建議大家動手操作一下,以深入理解Oracle的事務隔離機製,事務恢複原理。
本文出自數據和雲公眾號,原文鏈接
最後更新:2017-07-17 18:04:07