如何获取Informix连接会话对应的数据库服务器名称或别名?
问题描述
在AIX系统上运行Informix Dynamic Server Version 11.50,服务器配置了多个DB Server Aliases,分别监听不同TCP端口,sqlhosts文件内容如下:
# dbservername nettype hostname servicename options # DBSERVERNAME infx_1 onsoctcp host port1 # DBSERVERALIASES infx_2 onsoctcp host port2 infx_3 onsoctcp host port3
为记录数据库连接信息,使用了如下存储过程:
CREATE PROCEDURE public.sysdbopen() -- Log session details on database connection -- Doug Lawry, Oninit Consulting, August 2020 DEFINE session, process INTEGER; DEFINE dbname, client, program VARCHAR(255); -- Continue calling session after any error ON EXCEPTION RETURN; END EXCEPTION; -- Ignore high frequency or system users IF USER IN ('no_exceptions_for now') THEN RETURN; END IF LET session = DBINFO('sessionid'); LET dbname = TRIM(DBINFO('dbname')); SELECT pid, TRIM(hostname), TRIM(feprogram) INTO process, client, program FROM sysmaster:informix.syssessions WHERE sid = session; SYSTEM 'echo ' || '"' || CURRENT :: DATETIME YEAR TO SECOND || '|' || session || '|' || dbname || '|' || USER || '|' || client || '|' || process || '|' || program || '|"' || ' >> $INFORMIXDIR/logs/connection.log'; END PROCEDURE;
该存储过程能获取大部分所需信息,但无法区分连接时使用的是DB Server Name还是某个DB Server Aliases。尝试过DBSERVERNAME/SITENAME,但始终返回DB Server Name,即便连接用的是别名。需要找到方法获取该信息并添加到日志中。
解决方案
在Informix 11.50中,没有直接的内置函数可以获取连接时使用的服务器别名,但可以通过以下两种方式实现需求:
方法1:通过端口关联sqlhosts中的别名
每个DB Server Aliases对应唯一的TCP端口,因此可以通过会话使用的监听端口,反向匹配sqlhosts文件中的别名:
修改后的存储过程示例:
CREATE PROCEDURE public.sysdbopen() DEFINE session, process, port_num INTEGER; DEFINE dbname, client, program, sqlhosts_path VARCHAR(255); ON EXCEPTION RETURN; END EXCEPTION; IF USER IN ('no_exceptions_for now') THEN RETURN; END IF LET session = DBINFO('sessionid'); LET dbname = TRIM(DBINFO('dbname')); LET sqlhosts_path = '$INFORMIXDIR/etc/sqlhosts'; -- 若sqlhosts在自定义路径,替换此处 -- 获取会话进程ID、客户端地址和程序名 SELECT pid, TRIM(hostname), TRIM(feprogram) INTO process, client, program FROM sysmaster:informix.syssessions WHERE sid = session; -- 获取当前会话对应的监听端口 SELECT s_port INTO port_num FROM sysmaster:informix.sysnetstat WHERE s_pid = process AND s_type = 'listen'; -- 写入日志,同时从sqlhosts匹配端口对应的别名 SYSTEM 'echo ' || '"' || CURRENT :: DATETIME YEAR TO SECOND || '|' || session || '|' || dbname || '|' || USER || '|' || client || '|' || process || '|' || program || '|' || '$(awk ''$4 == "' || port_num || '" {print $1}'' ' || sqlhosts_path || ')' || '|"' || ' >> $INFORMIXDIR/logs/connection.log'; END PROCEDURE;
补充说明
- 如果sqlhosts中使用的是服务名而非直接端口号,需要先解析服务名对应的端口,可将awk命令改为:
$(awk ''$4 == "' || servicename || '" {print $1}'' ' || sqlhosts_path || ' | xargs getservbyname | awk ''{print $2}''') - 确保Informix运行用户有读取sqlhosts文件的权限
方法2:为每个别名配置独立的标识逻辑
如果应用可以配合调整连接参数,可以为每个别名设置独立的环境变量或逻辑库,在sysdbopen中读取该变量直接写入日志。比如:
- 应用连接
infx_2时,设置环境变量CONNECT_ALIAS=infx_2 - 在存储过程中添加
LET alias_name = TRIM(ENVIRONMENT('CONNECT_ALIAS'));,并将该变量写入日志
这种方法需要应用侧配合调整,灵活性较低,但实现更简单。
内容的提问来源于stack exchange,提问作者tjn
相关产品推荐
相关产品推荐

