【client_ip】通过v$session查询客户端的IP信息(一)

2014-11-24 16:45:34 · 作者: · 浏览: 0

我们想要查看连接数据库的客户端信息(主要是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