Alter system suspend/resume 導致的bug和特性

viadeazhu發表於2009-01-18

ORACLE:Oracle Database 11g Enterprise Edition Release 11.1.0.6.0

OS:redhat enterprise edition 2.6.18-8.el5 @ X86

From 11G Document:

"

The ALTER SYSTEM SUSPEND statement halts all input and output (I/O) to datafiles
(file header and file data) and control files. The suspended state lets you back up a
database without I/O interference. When the database is suspended all preexisting
I/O operations are allowed to complete and any new database accesses are placed in a
queued state.

"

According to BUG:3620559 on metalink:

"

"CONNECT /AS SYSDBA" HANG AFTER SUSPEND

"

我們可以很簡單的reproduce這個bug在11G @ liux上,有兩個命令可以導致這個bug:

Alter system flush shared_pool;

Alter system flush buffer_cache;

 

TEST case:

session 1 and session 2 login as sysdba;

session 1:

 alter system flush BUFFER_CACHE/SHARED_POOL;

session 2:

alter system suspend;

session 3:

sqlplus / as sysdba

-- it will hung by the wait event "writes stopped by instance recovery or database suspension".

當我們pstack這個hung住的程式:

: ~ > pstack 3531
#0  0x00ad1402 in __kernel_vsyscall ()
#1  0x0021ab54 in semtimedop () from /lib/libc.so.6
#2  0x0e57691f in sskgpwwait ()
#3  0x0e5758ae in skgpwwait ()
#4  0x0e2c3a44 in ksliwat ()
#5  0x0e2c33b1 in kslwaitctx. ()
#6  0x0e2c06f1 in kslwait ()
#7  0x0af1a640 in kcbwwa ()
#8  0x087fe162 in kcbzib ()
#9  0x0e348bb7 in kcbgtcr ()
#10 0x0e2ed288 in ktecgsc ()
#11 0x0e2ebad0 in ktecgetsh. ()
#12 0x0e2eba3a in ktecgshx ()
#13 0x0e2edd10 in kteinicnt1 ()
#14 0x0e4b668f in qertbFetch ()
#15 0x00000004 in ?? ()
#16 0x00000000 in ?? ()

會發現有kcb call,從這個bug metalink中:

kcbzib   KCB: input buffer - reads a block from disk into a buffer

原來"connect as sysdba"會有physical reads存在,如果在我們flush 了buffer_cache或者shared_pool後。

 

如果我們此時不幸地退出了所有其他sysdba的連線,那麼唯一讓系統恢復的辦法就只有kill掉oracle 程式(一般kill -9 就可以了)。

再重啟資料庫,此時會自動清掉 suspend的flag,select database_status from v$instance;會顯示active。

 

我又測試了對於一般的查詢,flush shared_pool 和flush buffer_cache的區別:

1.    如果只flush shared_pool,不flush buffer_cache,然後suspend system,再執行:

SQL>  select * from test test2;

        ID
----------
         1

在suspend時結果會返回,這是因為結果已經儲存在buffer_cache裡了,而這裡只需要hard parse一下就可以了。

可見在suspend的system中,hard parse是允許的,只要結果在buffer cache裡,不需要physical read,那麼結果也是可以返回的。

從10046 trace中可以證明這點:

PARSE #3:c=1999,e=2147,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=1232295633394990                    --hard parse發生

STAT #3 id=1 cnt=1 pid=0 pos=1 bj=12632 p='TABLE ACCESS FULL TEST (cr=3 pr=0 pw=0 time=0 us cost=2 size=13 card=1)'    --沒有physical read and write發生,所以可以執行。

 

2.   如果只flush buffer_cache,不flush shared_pool,然後suspend system,再執行:

SQL>  select * from test test2;

               ----it will hung

從10046 trace中看:

PARSE #1:c=0,e=192,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1232295772815066                            --沒有hard parse發生

每隔五秒會檢測一次,出現以下資訊:

WAIT #1: nam='writes stopped by instance recovery or database suspension' ela= 5008936 by thread#=2147483647 our thread#=1 p3=0 obj#=12453 tim=1232295807892952

重新resume system後,

STAT #1 id=1 cnt=1 pid=0 pos=1 bj=12632 p='TABLE ACCESS FULL TEST (cr=3 pr=2 pw=2 time=0 us cost=2 size=13 card=1)'       --兩次物理讀和寫

 

3.   在suspend之後,執行:

SQL> insert into test values (2);

1 row created.

SQL> commit;

    -- it will hung.

4.   在suspend之後,執行:

SQL> delete from test;

3 rows deleted.

SQL> exit

    --it will hung.

當resume後,10046:

WAIT #0: nam='log file sync' ela= 26545 buffer#=1978 p2=0 p3=0 obj#=12632 tim=1232298062864245

這兩個例子說明了當commit或正常退出時,從10046也可以看出,這是的hung是因為要“log file sync”,

也就是要在事務完成前將redo buffer寫入redo log中去,這裡是物理寫。

 

綜上,所以Alter system suspend;的一個重要特徵就是禁止任何檔案物理讀寫,這裡的檔案不僅包括datafile 和control file,也包括redo log。

而對於在buffer cache中的資料,可以有邏輯讀寫。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15415488/viewspace-541353/,如需轉載,請註明出處,否則將追究法律責任。

相關文章