SYS_CONTEXT

Oracle迁移应用,或需要在数据库层面实现精细化的操作审计与应用追踪时,SYS_CONTEXT函数提供了一个与 Oracle兼容的接口。此函数用于获取当前会话的用户、网络、应用等上下文信息,以支持安全策略、性能诊断和业务追踪等高级功能。

核心示例

以下示例展示了如何一次性查询当前会话的关键信息,如数据库名、会话用户、客户端IP地址和正在执行的应用模块,便于快速了解其核心用法。

SELECT
  SYS_CONTEXT('USERENV', 'DB_NAME') AS db_name,
  SYS_CONTEXT('USERENV', 'SESSION_USER') AS session_user,
  SYS_CONTEXT('USERENV', 'IP_ADDRESS') AS client_ip,
  SYS_CONTEXT('USERENV', 'MODULE') AS app_module;

预期输出示例(输出内容取决于实际会话环境):

 db_name | session_user |    client_ip    | app_module 
---------+--------------+-----------------+------------
 testdb  | dev_user     | 172.xx.xx.xx/xx | 

适用范围

您的PolarDB PostgreSQL版(兼容Oracle)集群的修订版本需为2.0.14.18.37.0及以上

说明

您可在控制台查看内核小版本号,也可以通过SHOW polardb_version;语句查看。如未满足内核小版本要求,请升级内核小版本

语法说明

SYS_CONTEXT(namespace VARCHAR2, attribute VARCHAR2) RETURN VARCHAR2

参数说明

  • namespace:命名空间,目前主要支持'USERENV'

  • attribute:要获取的属性名称。

返回值

VARCHAR2类型的属性值。

使用场景

配置并追踪应用信息

在复杂的应用中,追踪是哪个模块、哪个具体操作触发了数据库行为至关重要。SYS_CONTEXT不仅能读取信息,还能配合DBMS_APPLICATION_INFO包来设置和读取应用上下文,形成完整的追踪链路。

目的:为当前数据库会话设置应用模块和操作信息,以便后续审计或性能分析。

  1. 设置应用上下文信息

    在应用程序代码连接数据库后,调用DBMS_APPLICATION_INFO包中的过程来设置当前会话的模块和操作。

    -- 假设这是一个处理订单的后台服务
    CALL DBMS_APPLICATION_INFO.SET_MODULE('OrderProcessing', 'CreateNewOrder');
  2. 在数据库中查询上下文信息

    设置后,可在数据库的任何地方(例如,在触发器或日志记录函数中)通过SYS_CONTEXT获取这些信息。

    SELECT
      SYS_CONTEXT('USERENV', 'MODULE') AS current_module,
      SYS_CONTEXT('USERENV', 'ACTION') AS current_action;

    预期返回结果如下:

     current_module  | current_action 
    -----------------+----------------
     OrderProcessing | CreateNewOrder

在触发器中实现操作审计

SYS_CONTEXT在自动化审计场景中尤其有用。可在触发器中捕获操作者的环境信息,并将其存入审计日志,而无需应用层传递额外参数。

目的:当employees表的记录被更新时,自动在audit_log表中记录操作者的操作系统用户、客户端 IP 和会话 ID。

  1. 创建目标表并插入示例数据。

    创建employees表并插入一条用于测试的记录。

    CREATE TABLE employees (
        employee_id INT PRIMARY KEY,
        name TEXT,
        salary NUMERIC
    );
    INSERT INTO employees VALUES (101, 'test_user', 50000);
  2. 创建审计日志表

    用于存储审计信息。

    CREATE TABLE audit_log (
        log_id SERIAL PRIMARY KEY,
        table_name TEXT NOT NULL,
        os_user TEXT,
        client_ip TEXT,
        session_id TEXT,
        change_time TIMESTAMPTZ DEFAULT NOW()
    );
  3. 创建审计触发器函数

    该函数从USERENV命名空间中获取上下文信息并插入日志表。

    CREATE OR REPLACE FUNCTION fn_audit_employees_update()
    RETURNS TRIGGER AS $$
    BEGIN
        INSERT INTO audit_log (table_name, os_user, client_ip, session_id)
        VALUES (
            TG_TABLE_NAME,
            SYS_CONTEXT('USERENV', 'OS_USER'),
            SYS_CONTEXT('USERENV', 'IP_ADDRESS'),
            SYS_CONTEXT('USERENV', 'SESSIONID')
        );
        RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
  4. 绑定触发器到目标表

    employees表每次更新后执行此函数。

    CREATE TRIGGER trg_audit_employees_update
    AFTER UPDATE ON employees
    FOR EACH ROW
    EXECUTE FUNCTION fn_audit_employees_update();
  5. 验证审计功能

    执行一次更新操作,然后查询审计日志表。

    -- 模拟一次更新
    UPDATE employees SET salary = salary * 1.1 WHERE employee_id = 101;

    查询audit_log表,是否会自动新增一条记录,包含执行更新操作的用户的环境信息。

    SELECT * FROM audit_log;

    预期返回结果如下:

     log_id | table_name | os_user  |    client_ip        | session_id |          change_time           
    --------+------------+----------+---------------------+------------+--------------------------------
          1 | employees  | postgres | 172.xxx.xxx.xxx/xxx | 30         | 2025-10-17 07:41:50.666905 +00

属性详解

SYS_CONTEXT函数通过不同的参数获取多样的会话信息。属性名不区分大小写。

用户和会话信息

属性名

详细说明

示例

CURRENT_USER

当前有效用户。

SELECT SYS_CONTEXT('USERENV', 'CURRENT_USER');

SESSION_USER

会话初始用户。即客户端初始连接时进行身份验证的用户名,在整个会话期间保持不变。

SELECT SYS_CONTEXT('USERENV', 'SESSION_USER');

CURRENT_USERID

当前有效用户的ID。

SELECT SYS_CONTEXT('USERENV', 'CURRENT_USERID');

SESSION_USERID

会话初始用户的ID。

SELECT SYS_CONTEXT('USERENV', 'SESSION_USERID');

OS_USER

连接到数据库服务器的客户端操作系统用户名。

SELECT SYS_CONTEXT('USERENV', 'OS_USER');

ISDBA

判断当前用户是否为数据库超级管理员(Superuser)。

SELECT SYS_CONTEXT('USERENV', 'ISDBA');

会话标识信息

属性名

详细说明

示例

SESSIONID

会话标识符,通常是数据库后端的进程ID(PID)。两者功能相同,互为别名。

SELECT SYS_CONTEXT('USERENV', 'SESSIONID');

SID

CLIENT_IDENTIFIER

客户端标识符。

SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER');

CLIENT_INFO

客户端信息。

SELECT SYS_CONTEXT('USERENV', 'CLIENT_INFO');

数据库和模式信息

属性名

详细说明

示例

DB_NAME

当前连接的数据库名称。

SELECT SYS_CONTEXT('USERENV', 'DB_NAME');

DB_UNIQUE_NAME

数据库的唯一名称。

SELECT SYS_CONTEXT('USERENV', 'DB_UNIQUE_NAME');

CURRENT_SCHEMA

当前默认的模式名称。

SELECT SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA');

SESSION_SCHEMA

会话模式名称。

SELECT SYS_CONTEXT('USERENV', 'SESSION_SCHEMA');

INSTANCE

实例编号。

SELECT SYS_CONTEXT('USERENV', 'INSTANCE');

INSTANCE_NAME

实例名称。

SELECT SYS_CONTEXT('USERENV', 'INSTANCE_NAME');

网络和连接信息

属性名

详细说明

示例

IP_ADDRESS

客户端的IP地址.

SELECT SYS_CONTEXT('USERENV', 'IP_ADDRESS');

SERVER_HOST

数据库服务器的主机地址。

SELECT SYS_CONTEXT('USERENV', 'SERVER_HOST');

HOST

客户端的主机名。

SELECT SYS_CONTEXT('USERENV', 'HOST');

TERMINAL

客户端的终端标识。

SELECT SYS_CONTEXT('USERENV', 'TERMINAL');

应用程序信息

属性名

详细说明

示例

MODULE

当前应用程序模块名。

SELECT SYS_CONTEXT('USERENV', 'MODULE');

ACTION

当前执行的操作名。

SELECT SYS_CONTEXT('USERENV', 'ACTION');

DATABASE_ROLE

数据库角色。

SELECT SYS_CONTEXT('USERENV', 'DATABASE_ROLE');

语言和本地化信息

属性名

详细说明

示例

LANG

当前编码。

SELECT SYS_CONTEXT('USERENV', 'LANG');

LANGUAGE

完整的语言和区域设置。

SELECT SYS_CONTEXT('USERENV', 'LANGUAGE');

NLS_DATE_FORMAT

当前会话的日期显示格式。

SELECT SYS_CONTEXT('USERENV', 'NLS_DATE_FORMAT');

版本信息

属性名

详细说明

示例

SESSION_EDITION_ID

会话版本ID。

SELECT SYS_CONTEXT('USERENV', 'SESSION_EDITION_ID');

CURRENT_EDITION_ID

当前版本ID。

SELECT SYS_CONTEXT('USERENV', 'CURRENT_EDITION_ID');