1. 程式人生 > >A Case of ATO Exception

A Case of ATO Exception

異常症狀

2012-12-21下午Oracle ERP在銷售模組做ATO產品訂單進展時,沒有彈出任何錯誤,也沒有 彈出訂單進展的”確認”提示,直接跳到訂單頭資訊,行資訊中也沒有出現帶*的標準成品料 號。且所有的ATO訂單都無法完成訂單進展。導致特製單不能及時錄入系統,問題較為嚴重。

解決思路

使用topas檢視作業系統是否有異常程序;

登入系統檢視併發請求狀態;

查系統當前會話、程序數;

看資料庫警告日誌;

詳細過程

1. OS程序檢查

登入到erp,執行topas觀察系統程序使用資源情況。

2. 併發請求

職責路徑:system administrator » Concurrent » Manager » Administer 此時再檢視併發管理執行狀態,等待處理的請求 因只有系統管理員有該許可權,大家也可以通過SQL指令碼進行查詢,指令碼如下(可以APPS執行):

WITH requests_count AS
(SELECT COUNT(1) counts
   	FROM apps.fnd_concurrent_requests fcr
WHERE fcr.request_date > trunc(SYSDATE - 1)
 AND fcr.requested_start_date < trunc(SYSDATE + 1)
 AND fcr.phase_code IN ('P', 'R'))
SELECT 'Attention! Concurrent requests are up to ' || rc.counts "attention"
 	FROM requests_count rc
WHERE rc.counts > 300;

3. 系統當前程序、會話數

Oracle資料庫當前資料庫設定的最大程序數、會話數在資料初始引數中已經設定,可以查詢如下:

1)使用PL/SQL Developer,開啟Command Windows即可(以APPS執行)

SQL> show parameter processes
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
aq_tm_processes                      integer     2
db_writer_processes                  integer     1
job_queue_processes                  integer     10
log_archive_max_processes            integer     2
processes                            integer     800
 
SQL> show parameter sessions
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
java_max_sessionspace_size           integer     0
java_soft_sessionspace_limit         integer     0
license_max_sessions                 integer     0
license_sessions_warning             integer     0
logmnr_max_persistent_sessions       integer     1
mts_sessions                         integer     0
sessions                             integer     1600
shared_server_sessions               integer     0

2)使用SQL指令碼查詢,開啟SQL Windows,或者SQLPlus(以APPS執行)

select * from v$parameter p where p.NAME in ('processes','sessions');

再檢視當前系統的程序數、會話數。

SELECT COUNT(*) FROM v$process;	--當前程序數

SELECT COUNT(*) FROM v$session; --當前會話數

當以上數目非常接近系統設定的最大值時,系統就可能出現類似以上的問題,主要是超出最 大會話數,無法進行新的會話、連線等響應。

此時一般會手動處理一些過期的會話,主要是以下方式

--類似session/cookie的會話
SELECT 'kill -9 ' || b.spid
  FROM v$session a,
       v$process b,
       v$sqltext c
 WHERE a.paddr = b.addr
   AND a.username IS NOT NULL
   AND c.hash_value = a.sql_hash_value
   AND c.sql_text LIKE '%SESSION_COOKIE_DOMAIN%'
   AND a.sid != (SELECT sid FROM v$mystat WHERE rownum = 1);

--當前之前還沒有正常回收的forms會話
SELECT 'alter system kill session' || '''' || s.sid || ',' || s.serial# || ''';' oracle_level_kill
  FROM v$session s,
       v$process p
 WHERE s.paddr = p.addr
   AND s.sid IN (SELECT se.sid
                   FROM v$session se
                  WHERE sid IN (SELECT session_id FROM v$locked_object)
                    AND se.logon_time < trunc(SYSDATE))
   AND s.action LIKE 'FRM:%'
   AND s.STATUS = 'INACTIVE';

4.檢視資料庫警告日誌

資料庫警告日誌中記錄了資料庫在執行過程中的狀態資訊,包括髮生的錯誤。 登入到伺服器主機,如prodora,警告日誌檔案路徑:

注:
以上路徑也是在資料庫的初始化引數設定,查詢如下:
--PL/SQL Developer的Command Windows
SQL> show parameter background_dump_dest;
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
background_dump_dest                 string      /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/bdump

--sql指令碼
select * from v$parameter p where p.NAME in ('background_dump_dest');

如今天的警告日誌擷取如下:
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_5173482.trc:
ORA-00600: 內部錯誤程式碼,引數: [15419], [severe error during PL/SQL execution], [], [], [], [], [], []
ORA-06544: PL/SQL: 內部錯誤,引數: [77406], [], [], [], [], [], [], []
ORA-06553: PLS-801: 內部錯誤 [77406]
ORA-00018: 超出最大會話數
ORA-06512: 在"APPS.FND_SIGNON", line 239
Fri Dec 21 15:32:03 2012
Timed out trying to start process J002.
Fri Dec 21 15:32:43 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_3883030.trc:
ORA-00600: 內部錯誤程式碼,引數: [4414], [0], [0], [5454], [2], [], [], []
ORA-00018: 超出最大會話數
ORA-00018: 超出最大會話數
Fri Dec 21 15:33:55 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_688340.trc:
ORA-00600: 內部錯誤程式碼,引數: [15419], [severe error during PL/SQL execution], [], [], [], [], [], []
ORA-06544: PL/SQL: 內部錯誤,引數: [77406], [], [], [], [], [], [], []
ORA-06553: PLS-801: 內部錯誤 [77406]
ORA-00018: 超出最大會話數
ORA-06512: 在"APPS.FND_SIGNON", line 239
Fri Dec 21 15:33:55 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_6520900.trc:
ORA-00600: 內部錯誤程式碼,引數: [15419], [severe error during PL/SQL execution], [], [], [], [], [], []
ORA-06544: PL/SQL: 內部錯誤,引數: [77406], [], [], [], [], [], [], []
ORA-06553: PLS-801: 內部錯誤 [77406]
ORA-20001: Oracle 錯誤 -18:FND_SIGNON.AUDIT_END 中檢測到 ORA-00018: 超出最大會話數。
ORA-06512: 在"APPS.APP_EXCEPTION", line 72
ORA-06512: 在"APPS.FND_SIGNON", line 18
ORA-06512: 在"APPS.FND_SIGNON", line 317
Fri Dec 21 15:34:43 2012
Completed checkpoint up to RBA [0x514c6.2.10], SCN: 0x0771.4352af6c
Fri Dec 21 15:40:51 2012
Restarting dead background process QMN0
QMN0 started with pid=600
Fri Dec 21 15:41:06 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_6520900.trc:
ORA-00600: 內部錯誤程式碼,引數: [17285], [0x1103D2D58], [4294967295], [0x70000008B9DF418], [], [], [], []
Fri Dec 21 15:41:07 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_6520900.trc:
ORA-00600: 內部錯誤程式碼,引數: [17285], [0x1103D2D58], [4294967295], [0x70000008B9DF418], [], [], [], []
ORA-00600: 內部錯誤程式碼,引數: [17285], [0x1103D2D58], [4294967295], [0x70000008B9DF418], [], [], [], []
Fri Dec 21 15:42:37 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_4214832.trc:
ORA-00604: 遞迴 SQL 層 1 出現錯誤
ORA-00018: 超出最大會話數
ORA-06512: 在line 1
Fri Dec 21 15:42:40 2012
Errors in file /u1/PROD/prodora/proddb/9.2.0/admin/PROD_erpprod/udump/prod_ora_3190972.trc:
ORA-00604: 遞迴 SQL 層 1 出現錯誤
ORA-00018: 超出最大會話數
ORA-06512: 在line 1

通過發生的ORA-錯誤,以及應用的異常時間,基本可以確定是由於會話引起的以上異常,清 理一些過期的會話就可以解決。

特別說明

在作業系統中已經做了一些cron任務,定期預警或者執行會話清理。主要如下:

  • 定期清理過期會話(session)
  • 定期檢查死鎖(deadlock)
  • 定期檢查請求(requests)
  • 定期檢查無效物件、表空間等(invalidobject, tablespace, tablespaces)
  • 定期檢查資料庫警告日誌(checkalert.sh)

以上指令碼均會發送郵件通知。

檢視prodora定義的cron job

$ crontab -l
45 07,13,16 * * *   /u1/PROD/prodora/dailyduty.sh session  > /dev/null 2>&1
00 08 * * *   /u1/PROD/prodora/dailyduty.sh database > /dev/null 2>&1
05 08 * * *   /u1/PROD/prodora/dailyduty.sh instance > /dev/null 2>&1
10 08 * * *   /u1/PROD/prodora/dailyduty.sh datafiles > /dev/null 2>&1
15 08 * * *   /u1/PROD/prodora/dailyduty.sh tablespaces > /dev/null 2>&1
20 08 * * 5   /u1/PROD/prodora/dailyduty.sh tablespace > /dev/null 2>&1
00 10,16 * * *   /u1/PROD/prodora/dailyduty.sh deadlock > /dev/null 2>&1
00 15,16,17 * * *   /u1/PROD/prodora/dailyduty.sh requests > /dev/null 2>&1
00 08 * * 5   /u1/PROD/prodora/dailyduty.sh invalidobject > /dev/null 2>&1
55 23 * * 0-4   /u1/PROD/prodora/checkalert.sh > /dev/null 2>&1

主要指令碼dailyduty.sh

#!/bin/ksh
#abstract:
#oracle database alert jobs
#history:
#2012-06-11     [email protected]         first release
#variables
script_basepath=/u1/PROD/prodora/sql
mail_date=$(date +%Y-%m-%d\ %H:%M:%S)
receipt=[email protected]
hostname=$(hostname)

#path
ORACLE_HOME=/u1/PROD/prodora/proddb/9.2.0
export ORACLE_HOME
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$ORACLE_HOME/bin
export PATH
ORACLE_SID=PROD
export ORACLE_SID


#variabls
script_name=$1
if [ "${script_name}" == "" ]; then
   echo "script file name was empty!"
   exit 0
fi
script="${script_basepath}/${script_name}.sql"
if [ ! -e ${script} ]; then
   echo "sql script file ${script} does not exist!"
   exit 0
fi

#sql spool log file
sqllog="${script_basepath}/${script_name}.log"

#sqlplus logon
sqlplus -s '/as sysdba' << EOF
set feed off
set linesize 200
set pagesize 200
spool ${sqllog}
@${script}
spool off
exit
EOF

#grep spool file and kill processes
if [ "${script_name}" == "session" ]; then
   grep "kill -9" ${sqllog} | awk 'NR >1 {print $0}' | ksh
fi

#mail
if [ "${script_name}" != "session" ]; then
   if [ `cat ${sqllog} | wc -l` -gt 0 ]; then
       cat ${sqllog} | mail -s "${mail_date}:${hostname} dba daily check of ${script_name}" ${receipt} 
   fi
fi

參考

  • Oracle Database Administrator Guide
  • Oracle Application Administrator Guide
blog comments powered by Disqus