在 Oracle 数据库中,SYS_CONTEXT(namespace, parameter) 函数用于返回当前数据库会话的环境信息,例如用户、主机、实例、语言、会话 ID 等。这一机制在数据库审计、安全控制、运维脚本中非常实用。而在国产数据库达梦(DM8)中,虽然官方文档中并未明确介绍该函数,但经实测发现该函数依然可用,且与 Oracle 高度兼容。
基本语法:
SELECT SYS_CONTEXT('USERENV', '<参数名>') FROM dual;
DM官网没有找到关于SYS_CONTEXT函数的介绍,在v$ifun函数定义中是能找到的,根据这一周的学习情况来看,很多Oracle上的SQL在DM上依旧通用,下面就用ORACLE常用的 userenv namespace 在DM8上 测试一下
版本:DM Database Server 64 V8–03134284368-20250430-272000-20149 Pack1
dmdba@DAMENG:5236 SQL> select top 1 banner || id_code from v$version;
BANNER||ID_CODE
-----------------------------------------------------------------
DM Database Server 64 V8--03134284368-20250430-272000-20149 Pack1
dmdba@DAMENG:5236 SQL> @fun context
dmdba@DAMENG:5236 SQL> select name,class$ from v$ifun where name like upper('%&1%');
old value 1:select name,class$ from v$ifun where name like upper('%&1%');
new value 1:select name,class$ from v$ifun where name like upper('%context%');
NAME CLASS$
----------------- ----------------
CONTEXT_INDEX_DEF system function
CONTEXTDEF context function
SYS_CONTEXT context function
SYS_CONTEXT context function
used time: 1.860(ms). Execute id is 19911.
dmdba@DAMENG:5236 SQL>
dmdba@DAMENG:5236 SQL> @p COMPATIBLE_MODE
dmdba@DAMENG:5236 SQL> select para_name,para_value,DEFAULT_VALUE,SESS_VALUE,FILE_VALUE,para_type,DESCRIPTION from v$dm_ini where para_name like upper('%&1%');
old value 1:select para_name,para_value,DEFAULT_VALUE,SESS_VALUE,FILE_VALUE,para_type,DESCRIPTION from v$dm_ini where para_name like upper('%&1%');
new value 1:select para_name,para_value,DEFAULT_VALUE,SESS_VALUE,FILE_VALUE,para_type,DESCRIPTION from v$dm_ini where para_name like upper('%COMPATIBLE_MODE%');
PARA_NAME PARA_VALUE DEFAULT_VALUE SESS_VALUE FILE_VALUE PARA_TYPE DESCRIPTION
-------------------- ---------- ------------- ---------- ---------- --------- --------------------------------------------------------------------------------------------------------
COMPATIBLE_MODE 0 0 0 0 IN FILE Server compatible mode, 0:none, 1:SQL92, 2:Oracle, 3:MS SQL Server, 4:MySQL, 5:DM6, 6:Teradata, 7:PG
CASE_COMPATIBLE_MODE 1 1 1 1 SYS Case compatible mode, 0:none, 1:Oracle(simple case), 2:Oracle(simple case new rule), 4:Oracle(bool case)
XA_COMPATIBLE_MODE 0 0 0 0 SYS XA compatible mode, 0:none, 1:Oracle, 2:MySql
used time: 13.766(ms). Execute id is 19912.
测试出DM8 SYS_CONTEXT namespace可以用的userenv有16项,可能还有一些自定义的没有介绍。
| 参数名 | 中文说明 | DM8可用性 |
|---|---|---|
| CURRENT_SCHEMA | 当前模式名 | ✅(PANDA)⭐ |
| CURRENT_SCHEMAID | 当前模式ID | ✅(150995947) |
| CURRENT_USER | 当前用户名 | ✅(PANDA)⭐ |
| CURRENT_USERID | 当前用户ID | ✅(50331752) |
| SESSION_USER | 当前会话用户名 | ✅(PANDA) |
| SESSION_USERID | 当前会话用户ID | ✅(50331752)⭐ |
| DB_NAME | 数据库名 | ✅(DAMENG)⭐ |
| INSTANCE_NAME | 实例名 | ✅(DMORCL)⭐ |
| HOST | 客户端主机名 | ✅(panda101)⭐ |
| SERVER_HOST | 实例运行主机名 | ✅(panda101) |
| IP_ADDRESS | 客户端IP地址 | ✅(::ffff:192.168.66.101)⭐ |
| ISDBA | 当前用户是否为DBA | ✅(TRUE) |
| LANG | 语言简写(CN/EN) | ✅(EN) |
| LANGUAGE | 语言及编码方式 | ✅(ENGLISH.UTF8) |
| NETWORK_PROTOCOL | 通信协议类型 | ✅(TCP/IP) |
| SESSIONID / SID | 当前会话标识符 | ✅(195075224) |
| TERMINAL | 当前终端或计算机名 | ❌(NULL) |
| INSTANCE | 实例号(Oracle专用) | ❌ |
| ENTRYID | 审计会话标识符 | ❌ |
| NLS_TERRITORY | 当前地区设置 | ❌ |
| NLS_CURRENCY | 货币符号 | ❌ |
| NLS_CALENDAR | 日历类型 | ❌ |
| NLS_DATE_FORMAT | 日期格式 | ❌ |
| NLS_DATE_LANGUAGE | 日期语言 | ❌ |
| NLS_SORT | 排序规则 | ❌ |
| PROXY_USER | 代理用户 | ❌ |
| PROXY_USERID | 代理用户ID | ❌ |
| DB_DOMAIN | 数据库域名 | ❌ |
| OS_USER | 操作系统用户名 | ❌ |
| EXTERNAL_NAME | 外部认证用户名 | ❌ |
| BG_JOB_ID | 后台作业ID | ❌ |
| FG_JOB_ID | 前台作业ID | ❌ |
| AUTHENTICATION_TYPE | 用户认证方式 | ❌ |
| AUTHENTICATION_DATA | 用户认证附加信息 | ❌ |
更多 Predefined Parameters of Namespace USERENV 参照Oracle官网:https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/SYS_CONTEXT.html
OB V3.2.4 SYS_CONTEXT函数:https://www.oceanbase.com/docs/enterprise-oceanbase-database-cn-10000000000948086
常用的有CURRENT_USER、DB_NAME、INSTANCE_NAME、IP_ADDRESS、SESSIONID / SID,这些函数信息可以用来判断会话信息、区分判断生产测试环境、在SQL、存储过程、PL/SQL、Shell中判断会话信息。
比如现在一套核心的营业系统有生产和测试两套环境,如果没有进行堡垒机或者环境分离(用同一套设备就可以登陆两套环境),我们再进行一些测试变更前可以通过SYS_CONTEXT函数进行二次确认,比如测试环境数据库名字叫做bcvxxx、cs_xxx、test_xxx可以用DB_NAME、INSTANCE_NAME、IP_ADDRESS这些区分生产和测试,防止造成不可挽回的操作,尤其是删表、删库这个高危操作,一定要确认环境信息。
可以使用如下语句区分环境:
SELECT
SYS_CONTEXT('USERENV','DB_NAME') AS db_name,
SYS_CONTEXT('USERENV','INSTANCE_NAME') AS instance_name,
SYS_CONTEXT('USERENV','IP_ADDRESS') AS ip_addr,
SYS_CONTEXT('USERENV','HOST') AS client_host
FROM dual;
DB_NAME INSTANCE_NAME IP_ADDR CLIENT_HOST
------- ------------- ------------------- -----------
DAMENG DMORCL ::ffff:192.168.66.101 LAPTOP-xxxxxxx
用项目上常用的一个脚本举例,kill会话,通过v$sessions获取会话排除本会话:
select 'sp_close_session('|| sess_id||');--'||
USER_NAME || '@' || CLNT_HOST || ' (' || APPNAME || ');' commands_to_verify_and_run
from v$sessions
where &1
and sess_id != (select SYS_CONTEXT('USERENV','SESSIONID'));
在定位到行锁阻塞源的sid后可以直接生成kill脚本,并杀掉会话,执行示例:
dmdba@DAMENG:5236 SQL> @kill sess_id='195075224'
COMMANDS_TO_VERIFY_AND_RUN
-----------------------------------------------------
sp_close_session(195075224);--PANDA@panda101 (disql);
used time: 4.766(ms). Execute id is 19914.
dmdba@DAMENG:5236 SQL> sp_close_session(195075224);--PANDA@panda101 (disql);
DMSQL executed successfully
used time: 4.502(ms). Execute id is 19915.
会话连接超限,有部分异常用户或者用户正在执行批量DML可以根据用户名、sql_id进行匹配,批量kill,DM是单进程多线程结构不支持LOCAL=NO在操作系统层面杀,所以批量kill会话还是有必要的。
@kill <filter expression>
@kill seee_id=150
@kill +seee_id|user_name|CLNT_HOST|APPNAME|sql_id
@kill "event like '%lock%'"
当然这是一种思路,在编写存储过程或者脚本时没有想要的字段,结合动态视图做连接,比如写一个存储过程记录所有会话的连接信息,将登录用户、来源主机、客户端 IP,写入操作日志表,通过DDL触发器记录记录执行过的sql信息,执行用户、执行时间、主机、客户端 IP、操作系统用户等。
NULL表示不支持。
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','TERMINAL') terminal;
TERMINAL
--------
NULL
used time: 0.253(ms). Execute id is 19822.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','LANGUAGE') language;
LANGUAGE
------------
ENGLISH.UTF8
used time: 0.218(ms). Execute id is 19823.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','SESSIONID') sessionid;
SESSIONID
---------
195075224
used time: 0.199(ms). Execute id is 19824.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','SID') sessionid;
SESSIONID
---------
195075224
used time: 3.490(ms). Execute id is 19825.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','INSTANCE') instance;
INSTANCE
--------
NULL
used time: 0.395(ms). Execute id is 19826.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','ENTRYID') entryid;
ENTRYID
-------
NULL
used time: 0.282(ms). Execute id is 19827.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','ISDBA') isdba;
ISDBA
-----
TRUE
used time: 0.262(ms). Execute id is 19828.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NLS_TERRITORY') nls_territory;
NLS_TERRITORY
-------------
NULL
used time: 0.338(ms). Execute id is 19829.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NLS_CURRENCY') nls_currency;
NLS_CURRENCY
------------
NULL
used time: 0.290(ms). Execute id is 19830.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NLS_CALENDAR') nls_calendar;
NLS_CALENDAR
------------
NULL
used time: 0.308(ms). Execute id is 19831.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NLS_DATE_FORMAT') nls_date_format;
NLS_DATE_FORMAT
---------------
NULL
used time: 0.236(ms). Execute id is 19832.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NLS_DATE_LANGUAGE') nls_date_language;
NLS_DATE_LANGUAGE
-----------------
NULL
used time: 0.279(ms). Execute id is 19833.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NLS_SORT') nls_sort;
NLS_SORT
--------
NULL
used time: 0.833(ms). Execute id is 19834.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','CURRENT_USER') current_user;
CURRENT_USER
------------
PANDA
used time: 0.692(ms). Execute id is 19835.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','CURRENT_USERID') current_userid;
CURRENT_USERID
--------------
50331752
used time: 0.608(ms). Execute id is 19836.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','SESSION_USER') session_user;
SESSION_USER
------------
PANDA
used time: 0.800(ms). Execute id is 19837.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','SESSION_USERID') session_userid;
SESSION_USERID
--------------
50331752
used time: 1.145(ms). Execute id is 19838.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','PROXY_USER') proxy_user;
PROXY_USER
----------
NULL
used time: 0.765(ms). Execute id is 19839.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','PROXY_USERID') proxy_userid;
PROXY_USERID
------------
NULL
used time: 1.241(ms). Execute id is 19840.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','DB_DOMAIN') db_domain;
DB_DOMAIN
---------
NULL
used time: 1.467(ms). Execute id is 19841.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','DB_NAME') db_name;
DB_NAME
-------
DAMENG
used time: 0.854(ms). Execute id is 19842.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','HOST') host;
HOST
--------
panda101
used time: 0.903(ms). Execute id is 19843.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','OS_USER') os_user;
OS_USER
-------
NULL
used time: 1.175(ms). Execute id is 19844.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','EXTERNAL_NAME') external_name;
EXTERNAL_NAME
-------------
NULL
used time: 2.050(ms). Execute id is 19845.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','IP_ADDRESS') ip_address;
IP_ADDRESS
----------
::1
used time: 1.110(ms). Execute id is 19846.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','NETWORK_PROTOCOL') network_protocol;
NETWORK_PROTOCOL
----------------
TCP/IP
used time: 1.765(ms). Execute id is 19847.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','BG_JOB_ID') bg_job_id;
BG_JOB_ID
---------
NULL
used time: 1.223(ms). Execute id is 19848.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','FG_JOB_ID') fg_job_id;
FG_JOB_ID
---------
NULL
used time: 1.382(ms). Execute id is 19849.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','AUTHENTICATION_TYPE') authentication_type;
AUTHENTICATION_TYPE
-------------------
NULL
used time: 18.972(ms). Execute id is 19850.
panda@DAMENG:5236 SQL> select SYS_CONTEXT('USERENV','AUTHENTICATION_DATA') authentication_data;
AUTHENTICATION_DATA
-------------------
NULL
used time: 0.609(ms). Execute id is 19851.
文章
阅读量
获赞
