ITPub博客

首页 > 数据库 > Oracle > oracle DBMS_SYSTEM.KSDWRT 详解

oracle DBMS_SYSTEM.KSDWRT 详解

原创 Oracle 作者:dingjun123 时间:2026-05-11 21:12:58 0 删除 编辑
DBMS_SYSTEM.KSDWRT 是 Oracle 内部包中的过程,用于向 告警日志(alert log)或跟踪文件 写入自定义消息。以下是详细解析:

基本语法

sql
复制
DBMS_SYSTEM.KSDWRT(
    dest  IN  BINARY_INTEGER,  -- 输出目标
    msg   IN  VARCHAR2        -- 消息内容(最大 4000 字节));

参数详解

表格
参数 类型 说明
dest BINARY_INTEGER 输出目标标识
msg VARCHAR2 要写入的文本消息

dest 取值含义

表格
值 常量含义 输出位置
0 KSDWRT_ALERT 告警日志(alert log)
1 KSDWRT_TRACEFILE 会话跟踪文件(user dump dest)
2 KSDWRT_BOTH 同时写入告警日志 + 跟踪文件
3 KSDWRT_DEFAULT 默认行为(通常同 0)
你的触发器使用 2,表示 告警日志和跟踪文件双写。

实际输出位置

告警日志路径(dest=0 或 2)

bash
复制
# 12c+ 默认路径$ORACLE_BASE/diag/rdbms/<db_unique_name>/<instance_name>/trace/alert_<instance_name>.log# 11g 及以前$ORACLE_BASE/admin/<instance_name>/bdump/alert_<instance_name>.log

跟踪文件路径(dest=1 或 2)

bash
复制
# 12c+ $ORACLE_BASE/diag/rdbms/<db_unique_name>/<instance_name>/trace/<instance_name>_ora_<spid>.trc# 由触发器触发时,通常是数据库后台进程或共享服务器进程的跟踪文件

快速验证写入

sql
复制
-- 测试写入告警日志BEGIN
  DBMS_SYSTEM.KSDWRT(0, '[TEST] Message to alert log only');
  DBMS_SYSTEM.KSDWRT(1, '[TEST] Message to trace file only');
  DBMS_SYSTEM.KSDWRT(2, '[TEST] Message to both alert and trace');END;/
检查输出:
bash
复制
# 实时查看告警日志tail -f $ORACLE_BASE/diag/rdbms/orcl/orcl/trace/alert_orcl.log | grep TEST# 查找最新跟踪文件ls -lt $ORACLE_BASE/diag/rdbms/orcl/orcl/trace/*.trc | head -5

关键特性与限制

表格
特性 说明
权限要求 需要 SYSDBA 或 EXECUTE on DBMS_SYSTEM(默认仅 SYS 可执行)
事务特性 独立提交,不受当前事务 ROLLBACK 影响
并发安全 内部使用 latch 保护,多进程并发写入安全
格式限制 纯文本,无自动时间戳前缀(需手动拼接)
长度限制 单条消息 ≤ 4000 字节,超长自动截断
性能影响 极低,直接写 OS 文件,无数据库表操作

与其他日志方式对比

表格
方式 目标 用途 权限
DBMS_SYSTEM.KSDWRT alert/trace 文件 诊断、审计、追踪 SYS
DBMS_OUTPUT.PUT_LINE 客户端缓冲区 调试 PL/SQL 普通用户
UTL_FILE.PUT_LINE 自定义 OS 文件 应用日志 需目录权限
AUDIT / DBMS_FGA 审计表 合规审计 AUDIT_ADMIN
V$DIAG_INFO / ADR 诊断框架 结构化诊断 自动

你的触发器优化建议

当前代码潜在问题:
sql
复制
-- 原代码:时间戳拼接无空格,可读性差'at' ||to_char(sysdate,'yyyy-mm-dd hh24:mi:ss')  -- 输出: at2026-03-18 11:32:00
修正版本:
sql
复制
CREATE OR REPLACE TRIGGER trg_log_lock_safe  AFTER SERVERERROR ON DATABASEDECLARE
  v_msg VARCHAR2(4000);BEGIN
  IF (IS_SERVERERROR(28000)) THEN
    
    -- 预组装消息,避免多次拼接
    v_msg := '[ORA-28000] Account locked | User: ' || 
             NVL(SYS_CONTEXT('USERENV', 'AUTHENTICATED_IDENTITY'), 'N/A') ||
             ' | IP: ' || NVL(SYS_CONTEXT('USERENV', 'IP_ADDRESS'), 'N/A') ||
             ' | Time: ' || TO_CHAR(SYSDATE, 'yyyy-mm-dd hh24:mi:ss') ||
             ' | SID: ' || TO_CHAR(USERENV('SID'));
    
    -- dest=2:同时写入 alert log 和 trace,确保不丢失
    DBMS_SYSTEM.KSDWRT(2, v_msg);
    
  END IF;EXCEPTION  WHEN OTHERS THEN 
    NULL; -- 静默失败,避免阻断原始错误返回END;/

查看写入结果

sql
复制
-- 查找最近的 ORA-28000 记录SELECT message_text 
FROM x$dbgalertext  -- 12c+ 内存化 alert log 视图WHERE message_text LIKE '%ORA-28000%'ORDER BY originating_timestamp DESCFETCH FIRST 5 ROWS ONLY;
或操作系统层面:
bash
复制
# 过滤告警日志grep "ORA-28000" $ORACLE_BASE/diag/rdbms/*/trace/alert*.log | tail -10# 查找相关跟踪文件(按时间排序)find $ORACLE_BASE/diag -name "*.trc" -mtime -1 -exec grep -l "ORA-28000" {} \;


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/7655508/viewspace-3117570/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-05-07

  • 博文量
    45
  • 访问量
    90559