【client_ip】通過v$session查詢客戶端的IP信息

【client_ip】通過v$session查詢客戶端的IP信息
2014-02-26 09:27:56      0 個評論    來源:【client_ip】通過v$session查詢客戶端的IP信息  
收藏    我要投稿

我們想要查看連接數據庫的客戶端信息(主要是IP地址)可以通過v$session視圖,其中有幾個與客戶端信息相關的字段:

OSUSER

VARCHAR2(30)

Operating system client user name

PROCESS

VARCHAR2(12)

Operating system client process ID

MACHINE

VARCHAR2(64)

Operating system machine name

TERMINAL

VARCHAR2(30)

Operating system terminal name

PROGRAM

VARCHAR2(48)

Operating system program name

MODULE

VARCHAR2(48)

Name of the currently executing module as set by calling the DBMS_APPLICATION_INFO.SET_MODULE procedure

ACTION

VARCHAR2(32)

Name of the currently executing action as set by calling the DBMS_APPLICATION_INFO.SET_ACTION procedure

CLIENT_INFO

VARCHAR2(64)

Information set by the DBMS_APPLICATION_INFO.SET_CLIENT_INFO procedure

CLIENT_IDENTIFIER

VARCHAR2(64)

Client identifier of the session

下面看一個pl/sql developer連接的會話中,各字段的值爲多少(展示中去掉了部分無關字段):

SID 140

USERNAME SYSTEM

COMMAND 3

OWNERID 2147483644

TADDR

LOCKWAIT

STATUS ACTIVE

SERVER DEDICATED

SCHEMA# 5

SCHEMANAME SYSTEM

OSUSER ballontt

PROCESS 5864:4884

MACHINE WORKGROUP\BALLONTT-PC

TERMINAL BALLONTT-PC

PROGRAM plsqldev.exe

TYPE USER

MODULE PL/SQL Developer

MODULE_HASH 1190136663

ACTION SQL窗口 -新建

ACTION_HASH 2127054360

CLIENT_INFO

CLIENT_IDENTIFIER

有一個通過pl/sql developer工具連接的SID爲140的會話,我打開另一窗口新建一個會話,通過v$session視圖查看140會話的客戶端信息,通過各個字段的值可以知道客戶端的所在主機的機器名、OS名、客戶端是什麼樣的應用程序,但是client_info字段爲空值,並沒有IP信息。在查找會話是屬於哪臺客戶端時非常不方便。而有的時候,該字段就會有客戶端的IP信息。這樣一來,問題就產生了。什麼時候該字段有客戶端IP,什麼時候沒有呢?

Problem

V$session視圖中的client_info什麼時候有客戶端的IP地址信息呢?

Solution

1. dbms_application_info.set_client_info

在上面列表中,CLIENT_INFO字段的描述是:

Information set by the DBMS_APPLICATION_INFO.SET_CLIENT_INFOprocedure。

就是說,該字段的值是通過“DBMS_APPLICATION_INFO.SET_CLIENT_INFO”存儲過程來設置的。客戶端在開始一個會話時,首先執行一遍該存儲過程,用IP做爲該存儲過程的參數(即客戶端的信息)。此時通過v$session視圖中的client_info字段就可以看到存儲過程中定義的IP信息。

1)首先在遠程客戶端的sql*plus上登陸一個會話

C:\Users\ballontt>sqlplus system/oracle@ballontt

SQL> select userenv('sid') from dual;

USERENV('SID')

----------------------

139

SQL> select client_infofrom v$session where sid=139;

CLIENT_INFO

----------------------------------------------------------------

此時SID爲139的遠程會話的client_info字段爲空。

2)在SID爲139的會話中執行一次DBMS_APPLICATION_INFO.SET_CLIENT_INFO存儲過程,然後查詢v$session試圖中的client_inf字段o

SQL> begin

2 dbms_application_info.set_client_info('192.68.10.10');

3 end;

4 /

PL/SQL 過程已成功完成。

SQL> select client_info from v$session where sid=139;

CLIENT_INFO

----------------------------------------------------------------

192.68.10.10

所以說,當客戶端的應用在會話中使用了dbms_application_info包定義了IP信息時,我們可以就可以查到該會話在v$session試圖中的client_info字段信息。否則,v$session視圖中就沒有相應的IP信息。(dbms_application_info包中有還有類型功能的其它過程:set_action/set_module/set_session_longops)

2. 在服務器端建立觸發器

如果說1中的方法是在客戶端使用了dbms_application_info.set_client_info存儲過程,我們也可以利用該存儲過程在服務器端創建一個用戶登錄時觸發的觸發器。

1)使用sys用戶創建觸發器

SQL> create or replace triggerlogon_on_database after logon on database

2 begin

3 dbms_application_info.set_client_info(sys_context('userenv','ip_address'));

4 end;

5 /

該觸發器在用戶登錄時(即一個會話產生時),將該會話的的SID、IP地址寫進v$session;

2)創建成功後,在遠程客戶端新打開一個會話,然後查詢v$session種的client_info字段信息

C:\Users\ballontt>sqlplussystem/oracle@ballontt

SQL> select userenv('sid') from dual;

USERENV('SID')

--------------------

138

SQL> select sid,client_info fromv$session where sid=138;

SID CLIENT_INFO

--------------------------------------------------------------------------

138 192.168.10.1

我的遠程客戶端的IP地址就是192.168.10.1。

3. utl_inaddr存儲過程

在網上查看信息時有人提到utl_inaddr包中的兩個存儲過程可以分別根據主機名查詢到IP,或根據Ip查詢到主機名。

SQL>desc utl_inaddr;

FUNCTION GET_HOST_ADDRESS RETURNS VARCHAR2

Argument Name Type In/Out Default?

---------------------- --------------- ------ --------

HOST VARCHAR2 IN DEFAULT

FUNCTION GET_HOST_NAME RETURNS VARCHAR2

Argument Name Type In/Out Default?

----------------------- ---------------- ------ --------

IP VARCHAR2 IN DEFAULT

SQL>select utl_inaddr.get_host_address('ballontt01') from dual;

UTL_INADDR.GET_HOST_ADDRESS('BALLONTT01')

--------------------------------------------------------------------------------

192.168.1.11

我們可以看到主機名爲ballontt01機器的IP地址爲:192.168.1.11

甚至如果服務器可以聯網,我們可以查詢互聯網上主機名對應的IP

SQL>select utl_inaddr.get_host_address('www.baidu.com') from dual;

UTL_INADDR.GET_HOST_ADDRESS('WWW.BAIDU.COM')

--------------------------------------------------------------------------------

220.181.111.148

其工作原理:執行該過程時,首先獲取域名解析服務器(resolv.conf),在根據host.conf文件確定解析順序,因爲缺省是hosts文件優先解析,這個時候會又繼續讀取/etc/hosts文件。如果Hosts文件存在解析關係,則返回信息;如果不存在,則繼續詢問DNS服務器獲得解析地址,如果不能解析,則會報錯。

SQL> selectutl_inaddr.get_host_address('ballontt001') from dual;

selectutl_inaddr.get_host_address('ballontt001') from dual

*

ERROR at line 1:

ORA-29257: host ballontt001 unknown

ORA-06512: at"SYS.UTL_INADDR", line 19

ORA-06512: at"SYS.UTL_INADDR", line 40

ORA-06512: at line 1

如果在/etc/hosts加入ballontt001對應的IP後再次查詢:

100.100.100.100 ballontt001

SQL> selectutl_inaddr.get_host_address('ballontt001') from dual;

UTL_INADDR.GET_HOST_ADDRESS('BALLONTT001')

--------------------------------------------------------------------------------

100.100.100.100

所以有些生產環境中,試圖使用utl_inaddr包結合v$session視圖中的machine字段(會話的主機名)來查詢會話的IP時,因爲hosts文件和DNS服務器中沒有machine字段的信息而無法解析,進而導致報錯,無法得到我們想要的結果。

綜上所述,做爲一名DBA,如果要想獲得會話的IP,我們能做的就是方法2中的建立一個觸發器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章