暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

达梦数据库,开启审计功能,对性能有多大损耗?

原创 陈举超 1天前
24

一:审计数据的真实存储位置

测试审计功能的性能损耗之前,需要先搞清楚,达梦的审计数据实际存储位置在哪?
1.V$AUDITRECORDS表记录审计数据,审计记录看着像是存储在达梦数据库内的;
2.有新审计数据时,又会生成或更新 AUDIT_CJC_***_2026-6-22-14-56-23.log 操作系统级别的审计文件;

那么审计数据,到底是存储在 操作系统文件?还是存储在数据库表里?还是两个地方都存储呢?
也就是 V$AUDITRECORDS 表数据来源是哪?

很好验证,把操作系统级别的审计文件重命名就可以,如果 V$AUDITRECORDS 查询不出审计数据了,就说明 审计数据仅存储在操作系统文件上:
查看审计文件:

[dmdba@cjc-db-11 audit]$ ls -lrth /dm8/audit/
total 900M
-rw-r--r-- 1 dmdba dinstall 100M May 28 18:07 AUDIT_CJC_F3021903F30219036919E90E7841ABD7_2026-5-28-15-57-58.log
-rw-r--r-- 1 dmdba dinstall 100M Jun  1 17:27 AUDIT_CJC_02C0502102C0502155732BE07841ABD7_2026-6-1-10-47-57.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 14:30 AUDIT_CJC_3E015A3F3E015A3F0CC06EF57841ABD7_2026-6-22-14-26-30.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 14:56 AUDIT_CJC_33A0A6F733A0A6F745E204287841ABD7_2026-6-22-14-56-23.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 15:05 AUDIT_CJC_9B4C9DE19B4C9DE1EF5B92BE7841ABD7_2026-6-22-14-56-33.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 15:06 AUDIT_CJC_8D78FFB88D78FFB808D258AA7841ABD7_2026-6-22-15-5-33.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 15:07 AUDIT_CJC_DBD2A321DBD2A32156F2C8AC7841ABD7_2026-6-22-15-6-50.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 15:09 AUDIT_CJC_EC5D2635EC5D26356E9316F87841ABD7_2026-6-22-15-7-42.log
-rw-r--r-- 1 dmdba dinstall 100M Jun 22 15:17 AUDIT_CJC_8EE461368EE46136B1367EEE7841ABD7_2026-6-22-15-11-24.log

查看审计记录:

SQL> SELECT SQL_TEXT FROM V$AUDITRECORDS where username='CJC' and OBJNAME='SMALL_OPS_TEST' limit 3;

行号     SQL_TEXT                                                                           
---------- -----------------------------------------------------------------------------------
1          DECLARE     v_start NUMBER := DBMS_UTILITY.GET_TIME; BEGIN     FOR i IN 1..100000 LOOP         INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);         COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录     END LOOP;     DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start)); END;
2          DECLARE     v_start NUMBER := DBMS_UTILITY.GET_TIME; BEGIN     FOR i IN 1..100000 LOOP         INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);         COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录     END LOOP;     DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start)); END;
3          DECLARE     v_start NUMBER := DBMS_UTILITY.GET_TIME; BEGIN     FOR i IN 1..100000 LOOP         INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);         COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录     END LOOP;     DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start)); END;

已用时间: 1.677(毫秒). 执行号:804.

重命名审计记录文件所在目录:

[dmdba@cjc-db-11 dm8]$ mv audit audit_bak

再次查询 V$AUDITRECORDS

SQL> SELECT SQL_TEXT FROM V$AUDITRECORDS where username='CJC' and OBJNAME='SMALL_OPS_TEST' limit 3;
未选定行

已用时间: 0.512(毫秒). 执行号:803.

SQL> SELECT COUNT(*) FROM V$AUDITRECORDS;

行号     COUNT(*)            
---------- --------------------
1          0

已用时间: 0.939(毫秒). 执行号:805.

改回原名,可以查询到审计记录了

[dmdba@cjc-db-11 dm8]$ mv audit_bak audit

SQL> SELECT SQL_TEXT FROM V$AUDITRECORDS where username='CJC' and OBJNAME='SMALL_OPS_TEST' limit 3;

行号     SQL_TEXT                                                                           
---------- -----------------------------------------------------------------------------------
1          DECLARE     v_start NUMBER := DBMS_UTILITY.GET_TIME; BEGIN     FOR i IN 1..100000 LOOP         INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);         COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录     END LOOP;     DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start)); END;
2          DECLARE     v_start NUMBER := DBMS_UTILITY.GET_TIME; BEGIN     FOR i IN 1..100000 LOOP         INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);         COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录     END LOOP;     DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start)); END;
3          DECLARE     v_start NUMBER := DBMS_UTILITY.GET_TIME; BEGIN     FOR i IN 1..100000 LOOP         INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);         COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录     END LOOP;     DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start)); END;

已用时间: 1.677(毫秒). 执行号:804.

SQL> SELECT COUNT(*) FROM V$AUDITRECORDS;

行号     COUNT(*)            
---------- --------------------
1          200103

已用时间: 283.321(毫秒). 执行号:807.

可以看到,审计数据仅存储在 操作系统上的审计文件,没有存储在数据库内部。

二:开启审计记录的性能损耗

测试场景如下:

1.数据库启动和关闭

启动和关闭也会记录审计日志,测试开启审计后,是否会影响达梦实例的启停速度

2.执行大量SQL

因为审计数据主要记录SQL文本等信息,模拟批量执行大量SQL,评估对性能的损耗

3.大表查询

理论上开启审计,对大表查询影响很小,和数据量关系不大

4.大数据插入

理论上开启审计,对大表查询影响很小,和数据量关系不大

三:测试步骤如下:

未开启审计

1.数据库启动和关闭

记录达梦数据库启动、关闭的时间:
启动:

[dmdba@cjc-db-11 ~]$ DmServiceCJC start
Starting DmServiceCJC:                                     [ OK ]

查看启动耗时:1.7 秒

[dmdba@cjc-db-11 log]$ tail -10f dm_CJC_202606.log 
2026-06-22 14:32:07.525 [INFO] database P0000002507 T0000000000000002507  INI parameter DPC_2PC changed, the original value 1, new value 0
2026-06-22 14:32:07.531 [INFO] database P0000002507 T0000000000000002507  version info: enterprise
......
2026-06-22 14:32:09.250 [INFO] database P0000002507 T0000000000000002507  local instance name is CJC, mode is NORMAL, status is OPEN.
2026-06-22 14:32:09.250 [INFO] database P0000002507 T0000000000000002507  SYSTEM IS READY.
2026-06-22 14:32:09.250 [INFO] database P0000002507 T0000000000000002507  [for dem]SYSTEM IS READY.

关闭:

SQL> shutdown immediate;
操作已执行
已用时间: 1.221(毫秒). 执行号:0.

查看关闭耗时: 9 秒

[dmdba@cjc-db-11 log]$ tail -10f dm_CJC_202606.log 
2026-06-22 14:33:45.580 [INFO] database P0000002507 T0000000000000002528  Server is stopping...
2026-06-22 14:33:45.580 [INFO] database P0000002507 T0000000000000002528  listener closed  and all sessions disconnected
......
2026-06-22 14:33:54.875 [INFO] database P0000002507 T0000000000000002528  [for dem]SYSTEM SHUTDOWN SUCCESS.
2026-06-22 14:33:54.875 [INFO] database P0000002507 T0000000000000002528  DM Database Server shutdown successfully.
2026-06-22 14:33:54.875 [INFO] database P0000002507 T0000000000000002528  nsvr_notify_exit wakeup main thread to exit

2.执行大量SQL(执行10万条SQL)

-- 创建一个小型操作测试表
DROP TABLE IF EXISTS SMALL_OPS_TEST PURGE;
CREATE TABLE SMALL_OPS_TEST (
    ID   INT PRIMARY KEY,
    VAL  VARCHAR2(100)
);

测试脚本(循环执行 10 万次单行插入,每次独立提交)

SET SERVEROUTPUT ON
DECLARE
    v_start NUMBER := DBMS_UTILITY.GET_TIME;
BEGIN
    FOR i IN 1..100000 LOOP
        INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);
        COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start));
END;
/

DMSQL 过程已成功完成
已用时间: 00:00:33.554. 执行号:523.

3.大表查询

对 500 万行进行全表聚合计算。

SET TIMING ON;
-- 清理老表
DROP TABLE IF EXISTS BIG_TABLE PURGE;
DROP TABLE IF EXISTS BIG_TABLE_INSERT PURGE;
DROP TABLE IF EXISTS UPDATE_BIG PURGE;

-- 大表:500 万行
CREATE TABLE BIG_TABLE (
    ID       INT PRIMARY KEY,
    COL1     VARCHAR2(200),
    COL2     NUMBER,
    COL3     DATE
);

INSERT INTO BIG_TABLE
SELECT LEVEL,
       'DATA_' || LEVEL,
       DBMS_RANDOM.VALUE(1, 100000),
       DATE '2025-01-01' + LEVEL/(24*60)
FROM DUAL CONNECT BY LEVEL <= 5000000;
COMMIT;

记录时间:

影响行数 5000000
已用时间: 00:00:34.044. 执行号:505.
SQL> commit;
操作已执行
已用时间: 1.699(毫秒). 执行号:506.

– 收集统计信息
DBMS_STATS.GATHER_TABLE_STATS(USER, ‘BIG_TABLE’);
DMSQL 过程已成功完成
已用时间: 00:00:02.041. 执行号:507.

SELECT COUNT(*),
       AVG(COL2),
       MAX(COL3)
FROM BIG_TABLE
WHERE COL2 > 50000;
已用时间: 452.528(毫秒). 执行号:515.

4.大数据插入

将 500 万行全部插入到新建的空表中。

-- 创建空目标表
CREATE TABLE BIG_TABLE_INSERT AS
SELECT * FROM BIG_TABLE WHERE 1=0;

-- 批量写入测试
SET TIMING ON;
INSERT INTO BIG_TABLE_INSERT
SELECT * FROM BIG_TABLE;
COMMIT;

耗时:

已用时间: 00:00:29.835. 执行号:509.
SQL> commit;
操作已执行
已用时间: 1.389(毫秒). 执行号:510.

开启审计

开启审计功能

CALL SP_SET_ENABLE_AUDIT(1);

配置审计策略

SQL> SP_AUDIT_STMT('ALL', 'CJC', 'ALL');
DMSQL 过程已成功完成
已用时间: 1.711(毫秒). 执行号:603.

查看审计策略

SQL> select * from SYSAUDITOR.SYSAUDIT;

行号     LEVEL       UID         TVPID       COLID       TYPE        WHENEVER   
---------- ----------- ----------- ----------- ----------- ----------- -----------
1          1           -1          -1          -1          15          3
2          1           50331649    -1          -1          12          1
3          1           50331748    -1          -1          33          3
4          1           50331748    -1          -1          32          3
5          2           50331748    1049        1           50          1
6          1           50331748    -1          -1          0           3

6 rows got

已用时间: 1.247(毫秒). 执行号:602.
SELECT 
    "LEVEL",
    CASE "LEVEL"
        WHEN 1 THEN '语句级'
        WHEN 2 THEN '对象级'
        ELSE '其他'
    END AS 审计级别,
    UID AS 用户ID,
    TVPID AS 对象ID,
    COLID AS 列ID,
    CASE "TYPE"
        WHEN 0  THEN 'ALL'
        WHEN 12 THEN 'SELECT'
        WHEN 15 THEN 'DELETE'
        WHEN 32 THEN 'EXECUTE'
        WHEN 33 THEN 'INSERT'
        WHEN 34 THEN 'UPDATE'
        WHEN 50 THEN 'AUDIT'
        ELSE '其他(' || "TYPE" || ')'
    END AS 操作类型,
    CASE "WHENEVER"
        WHEN 1 THEN '仅成功'
        WHEN 2 THEN '仅失败'
        WHEN 3 THEN '不论成败'
        ELSE '未知'
    END AS 审计时机
FROM SYSAUDITOR.SYSAUDIT;


行号     LEVEL       审计级别 用户ID    对象ID    列ID       操作类型 审计时机
---------- ----------- ------------ ----------- ----------- ----------- ------------ ------------
1          1           语句级    -1          -1          -1          DELETE       不论成败
2          1           语句级    50331649    -1          -1          SELECT       仅成功
3          1           语句级    50331748    -1          -1          INSERT       不论成败
4          1           语句级    50331748    -1          -1          EXECUTE      不论成败
5          2           对象级    50331748    1049        1           AUDIT        仅成功
6          1           语句级    50331748    -1          -1          ALL          不论成败

6 rows got

已用时间: 0.578(毫秒). 执行号:702.

1.数据库启动和关闭

记录达梦数据库启动、关闭的时间:
启动:

[dmdba@cjc-db-11 ~]$ DmServiceCJC start
Starting DmServiceCJC:                                     [ OK ]

查看启动耗时:1.7 秒

[dmdba@cjc-db-11 log]$ tail -10f dm_CJC_202606.log 
2026-06-22 14:32:07.525 [INFO] database P0000002507 T0000000000000002507  INI parameter DPC_2PC changed, the original value 1, new value 0
2026-06-22 14:32:07.531 [INFO] database P0000002507 T0000000000000002507  version info: enterprise
......
2026-06-22 14:32:09.250 [INFO] database P0000002507 T0000000000000002507  local instance name is CJC, mode is NORMAL, status is OPEN.
2026-06-22 14:32:09.250 [INFO] database P0000002507 T0000000000000002507  SYSTEM IS READY.
2026-06-22 14:32:09.250 [INFO] database P0000002507 T0000000000000002507  [for dem]SYSTEM IS READY.

关闭:

SQL> shutdown immediate;
操作已执行
已用时间: 1.221(毫秒). 执行号:0.

耗时:8秒

2026-06-22 15:09:21.483 [INFO] database P0000003534 T0000000000000003555  Server is stopping...
2026-06-22 15:09:21.483 [INFO] database P0000003534 T0000000000000003555  listener closed  and all sessions disconnected
......
2026-06-22 15:09:29.729 [INFO] database P0000003534 T0000000000000003555  [for dem]SYSTEM SHUTDOWN SUCCESS.
2026-06-22 15:09:29.729 [INFO] database P0000003534 T0000000000000003555  DM Database Server shutdown successfully.
2026-06-22 15:09:29.729 [INFO] database P0000003534 T0000000000000003555  nsvr_notify_exit wakeup main thread to exit

2.执行大量SQL(执行10万条SQL)

– 创建一个小型操作测试表

DROP TABLE IF EXISTS SMALL_OPS_TEST PURGE;
CREATE TABLE SMALL_OPS_TEST (
    ID   INT PRIMARY KEY,
    VAL  VARCHAR2(100)
);

测试脚本(循环执行 10 万次单行插入,每次独立提交)

SET SERVEROUTPUT ON
DECLARE
    v_start NUMBER := DBMS_UTILITY.GET_TIME;
BEGIN
    FOR i IN 1..100000 LOOP
        INSERT INTO SMALL_OPS_TEST VALUES (i, 'data_' || i);
        COMMIT;  -- 每个 INSERT 都是一个独立的事务,产生一条审计记录
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('1 万次小事务耗时(百分秒): ' || (DBMS_UTILITY.GET_TIME - v_start));
END;
/

DMSQL 过程已成功完成
已用时间: 00:00:33.560. 执行号:519.

3.大表查询

对 500 万行进行全表聚合计算。

SET TIMING ON;
-- 清理老表
DROP TABLE IF EXISTS BIG_TABLE PURGE;
DROP TABLE IF EXISTS BIG_TABLE_INSERT PURGE;
DROP TABLE IF EXISTS UPDATE_BIG PURGE;

-- 大表:500 万行
CREATE TABLE BIG_TABLE (
    ID       INT PRIMARY KEY,
    COL1     VARCHAR2(200),
    COL2     NUMBER,
    COL3     DATE
);

INSERT INTO BIG_TABLE
SELECT LEVEL,
       'DATA_' || LEVEL,
       DBMS_RANDOM.VALUE(1, 100000),
       DATE '2025-01-01' + LEVEL/(24*60)
FROM DUAL CONNECT BY LEVEL <= 5000000;
COMMIT;

记录时间:

已用时间: 00:00:39.448. 执行号:505.

SQL> commit;
操作已执行
已用时间: 1.187(毫秒). 执行号:506.

– 收集统计信息

DBMS_STATS.GATHER_TABLE_STATS(USER, 'BIG_TABLE');
DMSQL 过程已成功完成
已用时间: 00:00:02.041. 执行号:507.
SELECT COUNT(*),
       AVG(COL2),
       MAX(COL3)
FROM BIG_TABLE
WHERE COL2 > 50000;
已用时间: 454.837(毫秒). 执行号:512.

4.大数据插入

将 500 万行全部插入到新建的空表中。

-- 创建空目标表
CREATE TABLE BIG_TABLE_INSERT AS
SELECT * FROM BIG_TABLE WHERE 1=0;

-- 批量写入测试
SET TIMING ON;
INSERT INTO BIG_TABLE_INSERT
SELECT * FROM BIG_TABLE;
COMMIT;
影响行数 5000000
已用时间: 00:00:07.234. 执行号:514.
SQL> commit;
操作已执行
已用时间: 1.809(毫秒). 执行号:515.

总结:

测试场景有限,仅供参考,测试的几个场景中,开启审计后,未发现有明显的性能损耗。
比较奇怪的地方是,开启审计后,大数据插入的速度反而比没开审计时变快了,重复执行了多次,都是开启审计后执行更快?

image.png

欢迎关注我的公众号《IT小Chen

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论