oracle查詢某個sql語句客戶端ip地址
1. 背景
業務出現異常后,或者某個sql導致系統卡頓。需要問題后需要溯源,需要獲取這個sql是在哪個客戶端的IP發起的。
2. cs架構
客戶端直接連接數據庫,可以很方便查詢,采用通過sql_id找到客戶端、進程或者port等,默認的模式是沒有ip地址記錄
select machine,program,port from GV$SESSION where sql_id=
或者
select machine,program,port from GV$ACTIVE_SESSION_HISTORY where sql_id=
select machine,program,port from dba_hist_ACTIVE_SESS_HISTORY where sql_id=
再通過數據庫監聽查詢或者應用服務器
2.1. 案例說明
select machine,program,port from GV$SESSION where sql_id=
或者 GV$ACTIVE_SESSION_HISTORY 的表獲取到

通過獲取machine、program、port這幾個字段。
再通過數據庫監聽日志只獲取
cat listener.log|grep 51880|grep Thin
注意:發現監控日志中記錄的計算機的主機名和session中記錄的可能不一致

3. BS架構
bs架構和cs架構的不同點,bs采用多層架構,是應用服務連接數據庫的,獲取到的ip也是應用服務器的ip地址。
以java應用服務器為例,需要查詢到客戶端的ip發起端。
有個技巧:java服務的應用名稱都是叫JDBC Thin Client,這樣一臺服務器中有多個java服務是無法區別的,可以手工區別名稱來定義不同的java服務,如java應用的配置文件中,針對鏈接池配置,這樣你的應用名稱就變成了oracle-monitor
data-source-properties:
"[v$session.program]": oracle-monitor
有以下幾種方式
- 通過nginx,客戶端連接nginx,nginx轉發到應用服務器中。再配置時間和請求的交易來定位,需要記錄應用服務器的日志,日志格式類似
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent $request_time $upstream_response_time "$http_referer" '
'$connection $upstream_addr "$http_x_forwarded_for" "$http_cookie" ';
$remote_addr:這個就是客戶端的ip
- 沒有nginx,應用容器采用tomcat,可以查看tomcat的請求日志

- 還有應用端記錄登錄日志來獲取
4. 數據庫登錄觸發器
登錄的時候,可以再session記錄ip地址,這樣就不需要到監控日志中去查詢具體的ip地址
CREATE OR REPLACE TRIGGER on_logon_trigger
AFTER LOGON ON DATABASE
BEGIN
DBMS_APPLICATION_INFO.SET_CLIENT_INFO(SYS_CONTEXT('USERENV', 'IP_ADDRESS'));
END;
SELECT * FROM gv$session WHERE client_info 這個字段中就會體現ip地址
5. 總結
追溯源頭的ip地址
- 通過慢的sql_id來獲取客戶端、應用、port,來定位ip地址。BS架構中應用服務名可以在鏈接池中設置不同的應用名。可以新增一個登錄的觸發器,記錄一下ip更加方便
- BS架構需要定位客戶端,需要通過請求和時間等,再通過nginx或者tomcat訪問日志來定位

浙公網安備 33010602011771號