1.查看后台是否有鎖:
SELECT sq.INST_ID,
SQ.SQL_TEXT, /*SQL文本*/
SE.SID, /*會話的唯一標識,通常要對某個會話進行分析前,首先就需要獲得該會話的SID。*/
SE.BLOCKING_SESSION,
SQ.OPTIMIZER_COST AS COST_, /* COST 值*/
SE.LAST_CALL_ET CONTINUE_TIME, /*執行時間*/
SE.EVENT, /*等待事件*/
SE.LOCKWAIT, /*是否等待LOCK(SE,P)*/
SE.MACHINE, /*客戶端的機器名。(WORKGROUP\PC-201211082055)*/
SQ.SQL_ID, /*SQL_ID*/
SE.USERNAME, /*創建該會話的用戶名*/
SE.LOGON_TIME, /*登陸時間*/
'ALTER SYSTEM KILL SESSION ''' || SE.SID || ',' || SE.SERIAL# ||
''';' KILL --若存在鎖情況,會用到KILL鎖釋放~
FROM gV$SESSION SE, /*會話信息。每一個連接到ORACLE數據庫的會話都能在該視圖中對應一條記錄,根據該視圖中的信息可以查詢該會話使用的用戶,正在執行或者剛剛執行的SQL語句*/
/**/
gV$SQLAREA SQ /*跟蹤所有SHARED POOL中的共享CURSOR信息,包括 執行次數,邏輯讀,物理讀等*/
WHERE SE.SQL_HASH_VALUE = SQ.HASH_VALUE
AND SE.STATUS = 'ACTIVE'
AND SE.SQL_ID = SQ.SQL_ID
AND SE.USERNAME = SQ.PARSING_SCHEMA_NAME
--過濾條件
AND SE.USERNAME = 'FWSB' --用戶名
and se.BLOCKING_SESSION is not null;

以下將重點的幾個列說明一下
SQL_TEXT——被鎖的語句;開發人員需要判斷,這里面有沒有反饋慢的功能對應的語句。
SID——被鎖的語句對應的SID;
BLOCKING_SESSION——鎖源頭,如圖所示,SID=510的語句導致SID=697的語句鎖了;
CONTINUE_TIME——被鎖的時間,單位為秒;
EVENT——被鎖語句的等待事件,比如read by other session,gc buffer busy acquire, enq:TX – row lock contention這些,
特別強調,如果看到enq:TX – row lock contention,這個是我們平時所說的鎖表,不同進程操作同一條數據。
MACHINE——被鎖語句的機器名,我們系統功能對應的應該為feng 或者 tiao,否則不是我們系統的語句;
SQL_ID——被鎖語句的SQL_ID;
如果慢的功能恰好在這里面被查出了,那么說明這個功能被鎖了。
這時候可以考慮把導致功能被鎖的語句發出來,讓其他開發人員確認一下對應功能。然后跟客戶或者運維同事反饋一下。
但是如果慢的功能沒有在這里面查出來,那需要按照接下來的流程處理了,有點繁瑣,但目前我這邊還沒有什么更好的方法。如果大家有,可以拿出來交流分享一下。
2.定位功能對應的語句

首先打開PLSQL,調出SESSION窗口,選擇上面的選擇框為ACTIVE SESSIONS 即正在執行中的進程。
然后查一下,當前執行的SESSION中,是否有慢的功能對應的語句,在“SQL文本”那個頁簽里面查找,
如果覺得這個頁簽展示的信息不足以幫助確定功能,可以選擇切換到“鎖”的頁簽,看到里面有OBJECT_NAME列,里面有功能涉及到的表名。C_TIME列有這個功能執行了多少秒,大體可以推測出功能是什么時間點觸發的。通過表名、時間,大概能判斷出是什么功能。如果通過這些還找不到,那可能需要找找別的原因了。如果一個開發人員表示自己也不清楚功能涉及到什么表,那我表示我已經無能為力了……
通過上面截圖的語句大概可以看出,這個進程跑的應該是全國業務,因為涉及到交互訂單項表和賬單表。但是具體業務功能,那需要全國模塊相關開發人員通過進程對應的語句具體分析了。(我這里只是隨便找了個語句舉例說明。)
有的時候,我們通過這種方式找到了慢的語句,但是粘貼出來發現有的地方是用‘冒號+數字’的形式展示的,這表示該處的參數使用了綁定變量。
此時,找到語句對應的SQL_ID,如圖所示,通過以下腳本查詢對應的綁定變量是多少
SELECT SQL_ID, NAME, DATATYPE_STRING, LAST_CAPTURED, VALUE_STRING
FROM GV$SQL_BIND_CAPTURE
WHERE SQL_ID = '00fb2hc1psmrb'
ORDER BY LAST_CAPTURED DESC, POSITION;
--在出問題的實例上執行,請自行替換SQL_ID,此時該SQL還在SHARED POOL中,沒有被AGED OUT
SELECT INSTANCE_NUMBER,
SQL_ID,
NAME,
DATATYPE_STRING,
LAST_CAPTURED,
VALUE_STRING
FROM DBA_HIST_SQLBIND
WHERE SQL_ID = '00fb2hc1psmrb'
ORDER BY LAST_CAPTURED DESC, POSITION;
--請自行替換SQL_ID,此時是從AWR中查詢。
將語句中的B1 B2分別替換結果中的,B1 B2;
需要注意的是,一定要對應要參數后面的時間與語句執行的時間是否相同,如果不同說明當時語句執行時,並不是使用該組參數。
如果第一個語句查不到結果,那么可以嘗試一下第二個語句。
因為數據庫存儲的記錄數量有限,如果這種兩個都無法找到你想找的對應時間點的參數,那就只能放棄了。
最后總結一下處理流程:
1. 先查是否被鎖;
2. 如果被鎖,則找源頭開發人員確認;如果沒有被鎖,查后台是否有功能對應的進程;
