glogin.sql配置不當引起sqlplus hang的假象分析

oliseh發表於2015-03-02

不久前遇到的一個問題,"故障"現象如下:
A主機上跑了兩個單例項的資料庫testa和testb,對testa例項進行例行重啟時先shutdown immediate,然後再透過sqlplus '/as sysdba'連進去嘗試重啟時發現,sqlplus Hang住不動了

sqlplus '/as sysdba'

SQL*Plus: Release 11.2.0.3.0 Production on Sat Feb 28 16:53:32 2015

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to an idle instance.     <====停在這裡不動了

此時使用sqlplus '/as sysdba'連線另一個例項testb是OK的,由於是測試環境於是將testb例項也shutdown immediate,準備重啟主機,重啟之前對於已經關閉的testb例項用sqlplus '/as sysdba'也無法連上去,現象同testa。主機重啟勢在必行了,但主機重啟後現象依舊,兩個例項都無法連線。使用"truss -dfaie -o /tmp/sched_trace.out.02271 sqlplus '/as sysdba'"命令對sqlplus '/as sysdba'的過程進行了跟蹤,直奔sched_trace.out.02271檔案結尾處發現了以下內容

2949918: 15664107: 0.8794:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/oraus.msb", O_RDONLY) = 8
2425346:        14746339: 0.8891:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/oraus.msb", O_RDONLY) = 6
2949918: 15664107: 0.8915:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/oraus.msb", O_RDONLY) = 8
2949918: 15664107: 0.8960:        statx("/oracle/app/oracle/product/11.2.0/db_1/sqlplus/admin/glogin.sql", 0x0FFFFFFFFFFFDA40, 176, 010) = 0
2949918: 15664107: 0.8963:        statfs("/oracle/app/oracle/product/11.2.0/db_1/sqlplus/admin/glogin.sql", 0x0FFFFFFFFFFFD620) = 0
2949918: 15664107: 0.8979:        kopen("/oracle/app/oracle/product/11.2.0/db_1/sqlplus/admin/glogin.sql", O_RDONLY|O_LARGEFILE) = 8
2425346:        14746339: 0.9041:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/oraus.msb", O_RDONLY) = 6
2949918: 15664107: 0.9065:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/oraus.msb", O_RDONLY) = 11
2949918: 15664107: 0.9086:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/oraus.msb", O_RDONLY) = 11
2425346:        14746339: 906.0540:        kopen("/oracle/app/oracle/product/11.2.0/db_1/rdbms/mesg/diaus.msb", O_RDONLY) = 5
2425346:        14746339: 906.0565:        statx("/oracle/app/oracle", 0x0FFFFFFFFFFFDAF0, 176, 0) = 0

從後往前查,diaus.msb=>oraus.msb=>glogin.sql,前面兩個檔案的大小和許可權與其他伺服器上的同名檔案相比較均一致,檢查glogin.sql的時候發現該檔案最近被修改過,其內容如下
set termout off
col newprom new_value newprom1
select > ' newprom from dual;
set sqlprompt '&newprom1'
set termout on
set serveroutput on

當例項還未啟動的時候這條sql是沒有任何結果的
select > ' newprom from dual;

導致接下來set sqlprompt '&newprom1'執行的時候變數newprom1值為空,從而會等待前臺輸入值給newprom1變數,這個等待的過程就會給使用者造成sqlplus hang住的假象,按照一般使用者的習慣發現sqlplus hang住時會頻繁的敲回車,敲完回車後sqlplus還是hang那裡。仔細分析一下敲回車後其實已經給newprom1變數賦值了,後續已經可以執行startup命令啟動instance了,只不過此時newprom1變數值為空,沒有回顯我們熟悉的SQL>到螢幕上,所以讓我們誤以為sqlplus hang住了。以下測試驗證上面的判斷:

'/as sysdba'

SQL*Plus: Release 11.2.0.3.0 Production on Mon Mar 2 10:35:36 2015

Copyright (c) 1982, 2011, Oracle.  All rights reserved.

Connected to an idle instance.    <===== sqlplus hang住了,但其實在等待前臺輸入

               <=====此處敲擊回車
startup    <=====執行起庫命令
ORACLE instance started.                                 

Total System Global Area 6413680640 bytes
Fixed Size                  2233480 bytes
Variable Size            4060089208 bytes
Database Buffers         2332033024 bytes
Redo Buffers               19324928 bytes
Database mounted.
Database opened.                                               <=====資料庫啟動成功

quit       <=====退出sqlplus

'/as sysdba'    <=====再次sqlplus連線資料庫

SQL*Plus: Release 11.2.0.3.0 Production on Mon Mar 2 10:38:37 2015

Copyright (c) 1982, 2011, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

>                                                            <=====這時提示符正常顯示了,因為instance啟動了

解決這個問題只要在glogin.sql里加入一行:為newprom1變數定義一個初始值(紅色部分)

set termout off
col newprom new_value newprom1
define newprom1="SQL> "
select > ' newprom from dual;
set sqlprompt '&newprom1'
set termout on
set serveroutput on

有了這個初始值,在instance未啟動的情況下,sqlplus連線後就會出現我們熟悉的SQL> 提示符,sqlplus就不會再hang住了。
需要注意的是還有一個作用於glogin.sql類似的檔案login.sql,執行sqlplus的時候會先去執行glogin.sql,然後會在當前目錄下尋找login.sql檔案,如果有的話執行login.sql;如果當前目錄沒有那麼到SQLPATH環境變數定義的路徑裡進一步尋找login.sql檔案如果找到的話執行login.sql內容。glogin.sql和login.sql的區別在於前者是全域性有效的,後者屬於每個使用者的個性化設定。有點像shell裡的.login和.profile的關係。
這個例子其實是glogin.sql給我們開了個小小的玩笑,提醒我們glogin.sql、login.sql是進入sqlplus的兩道關口,做配置的時候要不要輕視它們

 

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

相關文章