说明
测试过程比较单一,仅代表个人观点。
1.存储加密
为了防止用户直接通过数据文件获取用户信息,DM 提供了全面的数据加密的功能,包括:
透明加密 半透明加密 非透明加密
存储加密在保证数据文件安全性的同时,也会带来一定的性能影响,不同的加密算法对性能的影响各有不同,用户需要根据自己的需求来决定是否进行加密以及加密算法的选择。
1.1透明加密
1.1.1全库加密
对 DM 数据库进行全库加密需要在初始化数据库时通过 ENCRYPT_NAME 参数指定全库加密算法,加密密钥由 DM 自动生成。若初始化数据库时不指定 ENCRYPT_NAME 参数,则不进行全库加密。
ENCRYPT_NAME:全库加密使用的算法名。算法可以是 DM 内部支持的加密算法,或者是第三方的加密算法,其中 DM 支持的加密算法可通过查询动态视图 V$CIPHERS 得到,算法名为字符串,不能超过 128 个字节。
此参数在数据库创建成功后无法修改,可通过系统函数 SF_GET_ENCRYPT_NAME()获取此参数的设置值。
1.1.2表空间加密
DM 支持在创建表空间时指定进行透明加密,语法格式为:
CREATE TABLESPACE [IF NOT EXISTS] <表空间名> <数据文件子句> [<数据页缓冲池子句>] [<存储加密子句>] <存储加密子句> ::= ENCRYPT WITH <加密算法> [BY <加密密码>]
1.1.3操作:创建表空间并加密
---创建加密表空间CJC_ENCY CREATE TABLESPACE CJC_ENCY DATAFILE '/dm8/data/CJC/CJC_ENCY01.DBF' size 128 encrypt with DES_CFB; ---创建测试用户CJC_ENCY CREATE USER CJC_ENCY IDENTIFIED BY "******" DEFAULT TABLESPACE CJC_ENCY DEFAULT INDEX TABLESPACE CJC_ENCY; GRANT RESOURCE TO CJC_ENCY;
1.1.4操作:验证表空间已加密
select tablespace_name,encrypted from dba_tablespaces; 行号 tablespace_name encrypted ---------- --------------- --------- 1 SYSTEM N 2 ROLL N 3 TEMP N 4 MAIN N 5 CJC N 6 CJC_ENCY Y 7 MAIN N 7 rows got
1.1.5表列透明加密
DM 支持对表的列进行透明加密,支持建表时设置加密列,以及修改表定义时设置加密列。存储加密支持所有的列类型,包括大字段类型。用透明加密的方式加密列上的数据时,在数据库中保存加密该列的密钥,执行 DML 语句的过程中系统能自动获取密钥。
语法:
…… <列定义> ::= <不同类型列定义> [<列定义子句>][] [<透明存储加密子句>] <透明存储加密子句>::= <透明存储加密子句1>|<透明存储加密子句2> <透明存储加密子句1>::= ENCRYPT [<透明加密用法>] <透明存储加密子句2>::= ENCRYPT <透明加密用法><散列选项> <透明加密用法> ::= WITH <加密算法> [<透明加密选项>]| <透明加密选项> <透明加密选项> ::= <透明加密选项1> |<透明加密选项2> |<透明加密选项3> <透明加密选项1> ::= AUTO <透明加密选项2> ::= AUTO BY <列存储密钥> <透明加密选项3> ::= AUTO BY WRAPPED <列存储密钥的密文>
1.1.6操作:创建表为列加密
---创建非加密表空间CJCA CREATE TABLESPACE CJCA DATAFILE '/dm8/data/CJC/CJCA01.DBF' size 128; ---创建测试用户CJCA CREATE USER CJCA IDENTIFIED BY "******" DEFAULT TABLESPACE CJCA DEFAULT INDEX TABLESPACE CJCA; GRANT RESOURCE TO CJCA; ---创建测试表,使用加密列 disql CJCA/******:5238 CREATE TABLE T1(C1 INT, C2 INT ENCRYPT); CREATE TABLE T2(C1 INT, C2 INT ENCRYPT WITH DES_ECB); CREATE TABLE T3(C1 INT, C2 INT ENCRYPT WITH DES_ECB HASH WITH MD5 SALT); CREATE TABLE T4(C1 INT, C2 INT);
1.1.7操作:验证列被加密
select * from DBA_ENCRYPTED_COLUMNS; 行号 OWNER TABLE_NAME COLUMN_NAME ENCRYPTION_ALG SALT INTEGRITY_ALG ---------- ----- ---------- ----------- -------------- ---- ------------- 1 CJCA T1 C2 AES256_CBC NO NOMAC 2 CJCA T2 C2 DES_ECB NO NOMAC 3 CJCA T3 C2 DES_ECB YES MD5 已用时间: 15.693(毫秒). 执行号:801.
1.2半透明加密
1.2.1用户半透明加密
创建用户时可以指定存储加密密钥,这个密钥就是为了进行半透明加密时使用的。如果在创建用户时并没有指定存储加密密钥,系统也会自动为用户生成一个默认的加密密钥。
1.2.2表列半透明加密
如果在创建表或修改表时指定对表列进行半透明加密,DM 会使用用户的存储加密密钥对数据进行加密。半透明加密列的密文后追加了 4 个字节的 UID,用户查询数据时,若当前会话用户 ID 与列密文数据中存储的 UID 相同,则返回明文,否则返回 NULL。
1.2.3操作:表列半透明加密
---创建非加密表空间CJCB CREATE TABLESPACE CJCB DATAFILE '/dm8/data/CJC/CJCB01.DBF' size 128; ---创建测试用户CJCB CREATE USER CJCB IDENTIFIED BY "******" DEFAULT TABLESPACE CJCB DEFAULT INDEX TABLESPACE CJCB; GRANT RESOURCE TO CJCB; ---创建测试表,使用加密列 disql CJCB/******:5238 CREATE TABLE T1(C1 INT, C2 INT ENCRYPT MANUAL); CREATE TABLE T2(C1 INT, C2 INT ENCRYPT WITH DES_ECB MANUAL); CREATE TABLE T3(C1 INT, C2 INT ENCRYPT WITH DES_ECB MANUAL HASH WITH MD5 SALT); CREATE TABLE T4(C1 INT, C2 INT ENCRYPT MANUAL HASH WITH MD5 SALT);
1.2.4操作:验证表列透明加密设置成功
select * from DBA_ENCRYPTED_COLUMNS; 行号 OWNER TABLE_NAME COLUMN_NAME ENCRYPTION_ALG SALT INTEGRITY_ALG ---------- ----- ---------- ----------- -------------- ---- ------------- 1 CJCA T1 C2 AES256_CBC NO NOMAC 2 CJCA T2 C2 DES_ECB NO NOMAC 3 CJCA T3 C2 DES_ECB YES MD5 4 CJCB T1 C2 AES256_CBC NO NOMAC 5 CJCB T2 C2 DES_ECB NO NOMAC 6 CJCB T3 C2 DES_ECB YES MD5 7 CJCB T4 C2 AES256_CBC YES MD5 7 rows got
1.2.5操作:其他用户查看半透明加密数据测试
--- CJCB用户,对T1表插入数据 disql CJCB/******:5238 insert into t1 values(1,1),(2,2); commit; ---CJCB用户查看 SQL> select * from cjcb.t1; 行号 C1 C2 ---------- ----------- ----------- 1 1 1 2 2 2 已用时间: 0.733(毫秒). 执行号:1803. ---CJCA用户查看CJCB用户t1表数据 grant select any table to CJCA; disql CJCA/******:5238 SQL> select * from cjcb.t1; 行号 C1 C2 ---------- ----------- ----------- 1 1 NULL 2 2 NULL
半透明加密列显示为NULL,实际上有值
1.2.6操作:CJCB用户创建 T5 表,对 C1 列进行按列加密,加密列对用户 CJCA 和 CJC 可见。
--- CJCB用户新增表T5 disql CJCB/******:5238 CREATE TABLE T5(C1 INT ENCRYPT MANUAL USER (CJC,CJCA)); INSERT INTO CJCB.T5 VALUES(100); COMMIT; --- SYSDBA用户,查询不到CJCB的T5表C1列数据 disql SYSDBA/******:5238 SQL> select * from CJCB.T5; 行号 C1 ---------- ----------- 1 NULL --- CJCA用户,可以查询到CJCB的T5表C1列数据 disql CJCA/******:5238 SQL> SELECT * FROM CJCB.T5; 行号 C1 ---------- ----------- 1 100
1.3非透明加密
DM 对非透明加密的支持是通过对用户提供加解密接口实现的。用户在使用非透明加密时,需要提供密钥并调用加解密接口。采用非透明加密可以保证个人私密数据不被包括 DBA 在内的其他人获取。
非透明加密通过用户调用存储加密函数来进行,DM 提供了一系列的存储加密函数,还提供了一个数据加密包 DBMS_OBFUSCATION_TOOLKIT。
DM 提供了下列存储加密函数:
提供多个加密函数,以 CFALGORITHMSENCRYPT 函数为例:
加密:
CFALGORITHMSENCRYPT( SRC VARCHAR/TEXT/CLOB, ALGORITHM INT, KEY VARCHAR )
参数说明:
SRC:需要被加密的数据,数据类型可以为 VARCHAR、TEXT 或 CLOB。
ALGORITHM:加密算法 ID。加密算法对应的 ID 可通过查询 V$CIPHERS 得到。
KEY:采用的密钥。
功能说明:
对指定的明文进行加密,并返回密文。src 为 NULL 时, 加密结果也为 NULL。
当输入的参数为非法参数进而导致加密失败时,进行报错。
返回值:
加密后的密文,密文数据类型和 SRC 类型相同。
举例说明:
查看有哪些加密算法:
SQL> select * from V$CIPHERS where CYT_ID=514; 行号 CYT_ID CYT_NAME CYT_TYPE BLOCK_SIZE KH_SIZE EXTEND_SIZE WORK_MODE ---------- ----------- ---------- ----------- ----------- ----------- ----------- --------- 1 514 AES128_CBC 1 16 16 16 CBC 已用时间: 0.989(毫秒). 执行号:1207.
创建测试数据,对数据进行加密:
CREATE TABLE CJC.T0311(c1 VARCHAR(200));
INSERT INTO CJC.T0311 VALUES(CFALGORITHMSENCRYPT('达梦数据库非透明加密测试', 514, '仅供测试使用'));
COMMIT;
查询,数据已被加密:
SELECT * FROM CJC.T0311; 行号 c1 ---------- -------------------------------------------------------------------------------------------------- 1 0C7894F567F5B99354A39B6E0895BE37A7809FCD59BCA0B3B3567C5AAE63E13E2E353A03D9A5F31287358FFA421492ADFE 已用时间: 0.715(毫秒). 执行号:1211
解密:
CFALGORITHMSDECRYPT( SRC VARCHAR/TEXT/CLOB, ALGORITHM INT, KEY VARCHAR )
参数说明:
SRC:需要被解密的数据,数据类型可以为 VARCHAR、TEXT 或 CLOB。
ALGORITHM:加密算法 ID。加密算法对应的 ID 可通过查询 V$CIPHERS 得到。
KEY:采用的密钥。
功能说明:
对密文进行解密,并得到加密前的相同数据类型的明文。
当输入的参数为非法参数进而导致解密失败时,进行报错。
返回值:
解密后的明文,明文数据类型和 SRC 类型相同。
举例说明:
对数据进行解密:
SQL> SELECT CFALGORITHMSDECRYPT(c1, 514, '仅供测试使用') FROM CJC.T0311; 行号 CFALGORITHMSDECRYPT(c1,514,'仅供测试使用') ---------- ------------------------------------------------ 1 达梦数据库非透明加密测试 已用时间: 1.134(毫秒). 执行号:1212.
1.4数据文件strings测试
分别测试非加密、透明加密:加密表空间、透明加密:列加密、非透明加密:列加密对应数据文件的strings值。
01:非加密
disql SYSDBA/******:5238 ---创建表空间 CJC01 CREATE TABLESPACE CJC01 DATAFILE '/db/dm8/data/cjc/CJC0101.DBF' size 128; ---创建测试用户 CJC01 CREATE USER CJC01 IDENTIFIED BY "******" DEFAULT TABLESPACE CJC01 DEFAULT INDEX TABLESPACE CJC01; GRANT RESOURCE TO CJC01; disql CJC01/******:5238 create table t1(id int,name varchar(10),c1 int); insert into t1 values(1,'cjc',100); commit; 仅有1行 dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC0101.DBF|wc -l 1 dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC0101.DBF YT&p
02:透明加密:加密表空间
---创建加密表空间CJC02 CREATE TABLESPACE CJC02 DATAFILE '/db/dm8/data/cjc/CJC02.DBF' size 128 encrypt with DES_CFB; ---创建测试用户CJC02 CREATE USER CJC02 IDENTIFIED BY "******" DEFAULT TABLESPACE CJC02 DEFAULT INDEX TABLESPACE CJC02; GRANT RESOURCE TO CJC02; disql CJC02/******:5238 create table t1(id int,name varchar(10),c1 int); insert into t1 values(1,'cjc',100); commit; 有15354行: dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC02.DBF |wc -l 15354 dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC02.DBF |more FL-Rs BM}? Y[>8% 60=y 2CH lj#D BPy `TC!. ......
03:透明加密:加密列
---创建表空间 CJC03 CREATE TABLESPACE CJC03 DATAFILE '/db/dm8/data/cjc/CJC03.DBF' size 128; ---创建测试用户 CJC03 CREATE USER CJC03 IDENTIFIED BY "******" DEFAULT TABLESPACE CJC03 DEFAULT INDEX TABLESPACE CJC03; GRANT RESOURCE TO CJC03; disql CJC03/******:5238 create table t1(id int,name varchar(10) ENCRYPT WITH DES_ECB,c1 int ENCRYPT WITH DES_ECB); insert into t1 values(1,'cjc',100); commit; 有2行: dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC03.DBF|wc -l 2 dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC03.DBF Ep#w =3/m
04:非透明加密:加密列
---创建表空间 CJC04
CREATE TABLESPACE CJC04 DATAFILE '/db/dm8/data/cjc/CJC04.DBF' size 128;
---创建测试用户 CJC04
CREATE USER CJC04 IDENTIFIED BY "******" DEFAULT TABLESPACE CJC04 DEFAULT INDEX TABLESPACE CJC04;
GRANT RESOURCE TO CJC04;
disql CJC04/******:5238
create table t1(id int,name varchar(10),c1 int);
insert into t1 values(1,CFALGORITHMSENCRYPT('cjc',514,'仅供测试使用'),CFALGORITHMSENCRYPT(100,514,'仅供测试使用'));
[-6111]:字符串转换出错.
已用时间: 0.323(毫秒). 执行号:0.
alter table t1 modify c1 varchar(10);
insert into t1 values(1,CFALGORITHMSENCRYPT('cjc',514,'仅供测试使用'),CFALGORITHMSENCRYPT(100,514,'仅供测试使用'));
commit;
SQL> select * from t1;
行号 id name c1
---------- ----------- ---------------------------------- ----------------------------------
1 1 66AC566A88BB54BACE45881D96120DD0FE 400C6FD07E55F2B73BB39539E1447346FE
已用时间: 0.628(毫秒). 执行号:2835809.
select id,CFALGORITHMSDECRYPT(name, 514, '仅供测试使用') name,CFALGORITHMSDECRYPT(c1, 514, '仅供测试使用') c1 from t1;
行号 id name c1
---------- ----------- ---- ---
1 1 cjc 100
已用时间: 0.871(毫秒). 执行号:2835811.
有8行,而且直接显示了加密后的值?
dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC04.DBF|wc -l
8
dmdba@CJC-DB-001:/db/dm8/data/cjc$strings CJC04.DBF
6`;;
}4ul;
ul!;
wyv;
66AC566A88BB54BACE45881D96120DD0FE
400C6FD07E55F2B73BB39539E1447346FE
'Tg$S
VrsS
1.5加密性能测试
--- CJC用户创建测试数据
---创建非加密表空间CJC
CREATE TABLESPACE CJCB DATAFILE '/dm8/data/CJC/CJCB01.DBF' size 1024;
---创建测试用户CJC
CREATE USER CJCB IDENTIFIED BY "******" DEFAULT TABLESPACE CJCB DEFAULT INDEX TABLESPACE CJCB;
GRANT RESOURCE TO CJC;
---创建测试表,非加密
disql CJC/******:5238
-- 创建销售订单表
CREATE TABLE SALES_ORDER (
ORDER_ID BIGINT PRIMARY KEY, -- 销售单号,使用长整数并设为主键
SALES_PERSON VARCHAR(50), -- 销售员姓名
PRODUCT_NAME VARCHAR(100), -- 销售货物名称
AMOUNT DECIMAL(10, 2), -- 销售金额,保留两位小数
TRANSACTION_TIME TIMESTAMP, -- 交易时间,精确到时间戳
MEMO VARCHAR(200) -- 可选的备注列
);
-- 创建存储过程,参数num为要插入的行数
CREATE OR REPLACE PROCEDURE PROC_INSERT_SALES_ORDER(num IN INT)
AS
i INT;
BEGIN
i := 1; -- 初始化循环变量
WHILE i <= num LOOP
INSERT INTO SALES_ORDER (
ORDER_ID, SALES_PERSON, PRODUCT_NAME, AMOUNT, TRANSACTION_TIME, MEMO
) VALUES (
i, -- 销售单号递增
DBMS_RANDOM.STRING('U', 8), -- 随机销售员 [citation:3]
DBMS_RANDOM.STRING('U', 6), -- 随机货物 [citation:3]
ROUND(DBMS_RANDOM.VALUE(10, 10000), 2), -- 随机金额 [citation:3]
SYSTIMESTAMP - DBMS_RANDOM.VALUE(1, 365), -- 随机时间 [citation:6]
'Note_' || DBMS_RANDOM.STRING('A', 20) -- 随机备注
);
i := i + 1;
-- 每10000行提交一次,避免事务过大
IF MOD(i, 10000) = 0 THEN
COMMIT;
END IF;
END LOOP;
COMMIT; -- 提交剩余数据
END;
/
-- 调用存储过程,插入1000万行数据
CALL PROC_INSERT_SALES_ORDER(10000000);
DMSQL 过程已成功完成
已用时间: 00:01:39.012. 执行号:3006.
查看测试表大小:
SQL> select count(*) from CJC.SALES_ORDER;
行号 COUNT(*)
---------- --------------------
1 10000000
已用时间: 0.746(毫秒). 执行号:3102.
SQL> select bytes/1024/1024 from dba_segments where segment_name='SALES_ORDER';
行号 bytes/1024/1024
---------- --------------------
1 844
已用时间: 102.693(毫秒). 执行号:3101.
---创建非加密表空间CJCC
CREATE TABLESPACE CJCC DATAFILE '/dm8/data/CJC/CJCC01.DBF' size 128;
---创建测试用户CJCC
CREATE USER CJCC IDENTIFIED BY "******" DEFAULT TABLESPACE CJCC DEFAULT INDEX TABLESPACE CJCC;
GRANT RESOURCE TO CJCC;
1.5.1测试1:insert into 插入1千万行数据
CJC使用非加密表空间和非列加密:
CJCA使用的是加密表空间:
CJCB使用的是非加密表空间的列半透明加密:
---列半透明加密: -- 创建销售订单表,设置加密列 CREATE TABLE SALES_ORDER ( ORDER_ID BIGINT PRIMARY KEY, SALES_PERSON VARCHAR(50) ENCRYPT WITH DES_ECB MANUAL, PRODUCT_NAME VARCHAR(100) ENCRYPT WITH DES_ECB MANUAL, AMOUNT DECIMAL(10, 2) ENCRYPT WITH DES_ECB MANUAL, TRANSACTION_TIME TIMESTAMP ENCRYPT WITH DES_ECB MANUAL, MEMO VARCHAR(200) ENCRYPT WITH DES_ECB MANUAL );
CCJCC使用的是非加密表空间的列透明加密:
--- 列透明加密: -- 创建销售订单表,设置加密列 CREATE TABLE SALES_ORDER ( ORDER_ID BIGINT PRIMARY KEY, SALES_PERSON VARCHAR(50) ENCRYPT WITH DES_ECB, PRODUCT_NAME VARCHAR(100) ENCRYPT WITH DES_ECB, AMOUNT DECIMAL(10, 2) ENCRYPT WITH DES_ECB, TRANSACTION_TIME TIMESTAMP ENCRYPT WITH DES_ECB, MEMO VARCHAR(200) ENCRYPT WITH DES_ECB );
CJCA用户创建表 SALES_ORDER ,并插入数据:
disql CJCA/******:5238 CJCA用户创建表 SALES_ORDER ,并插入数据: SQL> insert into CJCA.SALES_ORDER select * from CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:15.759. 执行号:1402. SQL> commit; 操作已执行 已用时间: 2.921(毫秒). 执行号:1403. SQL> truncate table CJCA.SALES_ORDER; 操作已执行 已用时间: 17.525(毫秒). 执行号:1404. SQL> insert into CJCA.SALES_ORDER select * from CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:18.674. 执行号:1405. SQL> commit; 操作已执行 已用时间: 3.121(毫秒). 执行号:1406.
CJCB用户创建表 SALES_ORDER ,并插入数据:
shutdown immediate; disql CJCB/******:5238 insert into CJCB.SALES_ORDER select * from CJC.SALES_ORDER; SQL> insert into CJCB.SALES_ORDER select * from CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:28.454. 执行号:601. SQL> commit; 操作已执行 已用时间: 2.799(毫秒). 执行号:602. SQL> truncate table CJCB.SALES_ORDER; 操作已执行 已用时间: 24.268(毫秒). 执行号:603. SQL> insert into CJCB.SALES_ORDER select * from CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:25.551. 执行号:604. SQL> COMMIT; 操作已执行 已用时间: 2.756(毫秒). 执行号:605.
CJCC用户创建表 SALES_ORDER ,并插入数据:
shutdown immediate; disql CJCC/******:5238 SQL> insert into CJCC.SALES_ORDER select * from CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:24.100. 执行号:701. SQL> commit; 操作已执行 已用时间: 2.369(毫秒). 执行号:702. SQL> truncate table CJCC.SALES_ORDER; 操作已执行 已用时间: 11.734(毫秒). 执行号:703. SQL> insert into CJCC.SALES_ORDER select * from CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:25.289. 执行号:704. SQL> COMMIT; 操作已执行 已用时间: 2.194(毫秒). 执行号:705.
CJC:
[dmdba@cjc-db-03 ~]$ disql CJC/******:5238 服务器[LOCALHOST:5238]:处于主库打开状态 登录使用时间 : 4.357(ms) disql V8 SQL> CREATE TABLE SALES_ORDER_BAK AS SELECT * FROM SALES_ORDER WHERE 1=2; SQL> INSERT INTO CJC.SALES_ORDER_BAK SELECT * FROM CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:07.008. 执行号:701. SQL> COMMIT; 操作已执行 已用时间: 2.579(毫秒). 执行号:702. SQL> TRUNCATE TABLE CJC.SALES_ORDER_BAK; 操作已执行 已用时间: 16.635(毫秒). 执行号:703. SQL> SQL> INSERT INTO CJC.SALES_ORDER_BAK SELECT * FROM CJC.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:06.729. 执行号:704. SQL> COMMIT; 操作已执行 已用时间: 2.689(毫秒). 执行号:705. SQL> INSERT INTO CJC.SALES_ORDER_BAK SELECT * FROM CJCB.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:06.993. 执行号:707. SQL> COMMIT; 操作已执行 已用时间: 2.713(毫秒). 执行号:708.
SQL> select owner,bytes/1024/1024 from dba_segments where segment_name='SALES_ORDER' order by 1; 行号 owner bytes/1024/1024 ---------- ----- -------------------- 1 CJC 844 2 CJCA 844 3 CJCB 1315 4 CJCC 1122 已用时间: 84.180(毫秒). 执行号:1502.
1.5.2测试2:更新数据
新增测试存储过程,测试单条update SALES_ORDER 表的性能,要求固定的数据,当前 SALES_ORDER 表 ORDER_ID=3行的MEMO列值是Note_neWopbLjXLjxhmOIfKAq,要求更新为 Note_neWopbLjXLjxhmOIfABC,然后再更新回Note_neWopbLjXLjxhmOIfKAq,反复重复10万次,每update一条,commit提交一次
CJC/CJCA/CJCB/CJCC 用户创建测试存储过程:
disql CJC/******:5238 CREATE OR REPLACE PROCEDURE test_update_simple AS BEGIN FOR i IN 1..100000 LOOP IF MOD(i, 2) = 1 THEN UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfABC' WHERE ORDER_ID = 3; ELSE UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfKAq' WHERE ORDER_ID = 3; END IF; COMMIT; END LOOP; END; / SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:12.328. 执行号:5. SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:20.886. 执行号:1001.
disql CJCA/******:5238 CREATE OR REPLACE PROCEDURE test_update_simple AS BEGIN FOR i IN 1..100000 LOOP IF MOD(i, 2) = 1 THEN UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfABC' WHERE ORDER_ID = 3; ELSE UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfKAq' WHERE ORDER_ID = 3; END IF; COMMIT; END LOOP; END; / SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:23.786. 执行号:702. SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:23.561. 执行号:701.
disql CJCB/******:5238 CREATE OR REPLACE PROCEDURE test_update_simple AS BEGIN FOR i IN 1..100000 LOOP IF MOD(i, 2) = 1 THEN UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfABC' WHERE ORDER_ID = 3; ELSE UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfKAq' WHERE ORDER_ID = 3; END IF; COMMIT; END LOOP; END; / SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:20.650. 执行号:802. SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:19.433. 执行号:801
disql CJCC/******:5238 CREATE OR REPLACE PROCEDURE test_update_simple AS BEGIN FOR i IN 1..100000 LOOP IF MOD(i, 2) = 1 THEN UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfABC' WHERE ORDER_ID = 3; ELSE UPDATE SALES_ORDER SET MEMO = 'Note_neWopbLjXLjxhmOIfKAq' WHERE ORDER_ID = 3; END IF; COMMIT; END LOOP; END; / SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:30.450. 执行号:902. SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:15.183. 执行号:901.
1.5.3测试3:查询数据
CJC/CJCA/CJCB/CJCC 用户创建数据查询:
SELECT COUNT(*) FROM ( SELECT SALES_PERSON,PRODUCT_NAME,SUM(amount) FROM SALES_ORDER GROUP BY SALES_PERSON,PRODUCT_NAME ) A; disql CJC/******:5238 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:09.289. 执行号:1401. 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:09.133. 执行号:1402. disql CJCA/******:5238 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:11.102. 执行号:1101. 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:09.531. 执行号:1102. disql CJCB/******:5238 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:14.905. 执行号:1201. 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:12.659. 执行号:1202. disql CJCC/******:5238 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:13.921. 执行号:1301. 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:12.383. 执行号:1302.
1.5.4测试4:表数据量
插入1000万行相同数据后,表数据量:
SELECT (SELECT COUNT(*) FROM CJC.SALES_ORDER) AS CJC_TAB_COUNT, (SELECT COUNT(*) FROM CJCA.SALES_ORDER) AS CJCA_TAB_COUNT, (SELECT COUNT(*) FROM CJCB.SALES_ORDER) AS CJCB_TAB_COUNT, (SELECT COUNT(*) FROM CJCC.SALES_ORDER) AS CJCC_TAB_COUNT; 行号 CJC_TAB_COUNT CJCA_TAB_COUNT CJCB_TAB_COUNT CJCC_TAB_COUNT ---------- -------------------- -------------------- -------------------- -------------------- 1 10000000 10000000 10000000 10000000 SQL> select owner,bytes/1024/1024 from dba_segments where segment_name='SALES_ORDER' order by 1; 行号 owner bytes/1024/1024 ---------- ----- -------------------- 1 CJC 844 2 CJCA 844 3 CJCB 1315 4 CJCC 1122 已用时间: 84.180(毫秒). 执行号:1502.
1.5.5测试5:非透明加密
非透明加密测试,随机生成的一千万条数据内容和前面测试的SQL不同(带有加解密函数)、数据不同(大小相同),仅供参考。
---创建非加密表空间 CJCD
CREATE TABLESPACE CJCD DATAFILE '/dm8/data/CJC/CJCD01.DBF' size 128;
---创建测试用户CJCD
CREATE USER CJCD IDENTIFIED BY "******" DEFAULT TABLESPACE CJCD DEFAULT INDEX TABLESPACE CJCD;
GRANT RESOURCE TO CJCD;
GRANT SELECT ANY TABLE TO CJCD;
disql CJCD/******:5238
CREATE TABLE SALES_ORDER (
ORDER_ID BIGINT PRIMARY KEY,
SALES_PERSON VARCHAR(50),
PRODUCT_NAME VARCHAR(100),
AMOUNT DECIMAL(10, 2),
TRANSACTION_TIME TIMESTAMP,
MEMO VARCHAR(200)
);
CREATE OR REPLACE PROCEDURE PROC_INSERT_SALES_ORDER(num IN INT)
AS
i INT;
v_sales_person_plain VARCHAR(50);
v_product_name_plain VARCHAR(100);
v_memo_plain VARCHAR(200);
BEGIN
i := 1;
WHILE i <= num LOOP
-- 生成随机明文字符串
v_sales_person_plain := DBMS_RANDOM.STRING('U', 8); -- 8位大写字母
v_product_name_plain := DBMS_RANDOM.STRING('U', 6); -- 6位大写字母
v_memo_plain := 'Note_' || DBMS_RANDOM.STRING('A', 20); -- 带前缀的随机字符串
-- 插入加密后的数据
INSERT INTO SALES_ORDER (
ORDER_ID,
SALES_PERSON,
PRODUCT_NAME,
AMOUNT,
TRANSACTION_TIME,
MEMO
) VALUES (
i, -- 销售单号递增
CFALGORITHMSENCRYPT(v_sales_person_plain, 514, '仅供测试使用'), -- 加密销售员
CFALGORITHMSENCRYPT(v_product_name_plain, 514, '仅供测试使用'), -- 加密货物名
ROUND(DBMS_RANDOM.VALUE(10, 10000), 2), -- 随机金额
SYSTIMESTAMP - DBMS_RANDOM.VALUE(1, 365), -- 随机交易时间
CFALGORITHMSENCRYPT(v_memo_plain, 514, '仅供测试使用') -- 加密备注
);
i := i + 1;
-- 每10000行提交一次
IF MOD(i, 10000) = 0 THEN
COMMIT;
END IF;
END LOOP;
COMMIT; -- 提交剩余数据
END;
/
SQL> call PROC_INSERT_SALES_ORDER(10000000);
DMSQL 过程已成功完成
已用时间: 00:02:12.892. 执行号:1603.
大数据量插入测试:
CREATE TABLE CJCD.SALES_ORDER_01 AS SELECT * FROM CJCD.SALES_ORDER WHERE 1=2; SQL> INSERT INTO CJCD.SALES_ORDER_01 SELECT * FROM CJCD.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:16.917. 执行号:1606. SQL> COMMIT; 操作已执行 已用时间: 9.998(毫秒). 执行号:1607. SQL> TRUNCATE TABLE CJCD.SALES_ORDER_01; 操作已执行 已用时间: 22.092(毫秒). 执行号:1608. SQL> INSERT INTO CJCD.SALES_ORDER_01 SELECT * FROM CJCD.SALES_ORDER; 影响行数 10000000 已用时间: 00:00:16.422. 执行号:1609. SQL> COMMIT; 操作已执行 已用时间: 14.557(毫秒). 执行号:1610.
数据量查看:
SELECT OWNER,SEGMENT_NAME,BYTES/1024/1024 FROM DBA_SEGMENTS WHERE SEGMENT_NAME LIKE 'SALES_ORDER%' ORDER BY 1,2; 行号 OWNER SEGMENT_NAME BYTES/1024/1024 ---------- ----- --------------- -------------------- 1 CJC SALES_ORDER 844 2 CJC SALES_ORDER_BAK 844 3 CJCA SALES_ORDER 844 4 CJCB SALES_ORDER 1315 5 CJCC SALES_ORDER 1122 6 CJCD SALES_ORDER 1776 7 CJCD SALES_ORDER_01 1776 7 rows got 已用时间: 83.344(毫秒). 执行号:1702
查看数据,SALES_PERSON/PRODUCT_NAME/MEMO 三个列被加密了:
SQL> select * from SALES_ORDER limit 3; 行号 ORDER_ID SALES_PERSON PRODUCT_NAME AMOUNT TRANSACTION_TIME ---------- -------------------- ---------------------------------- ---------------------------------- ------- -------------------------- MEMO ------------------------------------------------------------------ 1 1 C1756E55F28329987763721694D268E1FE 5AE8A09A4DA4A5A73491A89844805B97FE 5503.68 2025-05-19 14:02:08.193946 C222B3F66A6C0B961543B882F392892A2C35028473CD7991FF6A9A4B48953280FE 2 2 2E9F2DC3A4D58E38A53BF9F17E1FDAF5FE 0556EFD3F77245A2E261310D155A0198FE 7453.94 2026-01-24 22:25:28.114335 4472A63449F7F0F73A5833F90519F123D8DEAFF360D8C70C9C572A84CCADA69AFE 3 3 B18FEBB00C41E4E186B0CA5AAF280501FE 2D4D0274AFB2508539E9E0D06AF4730EFE 1883.67 2025-09-13 00:17:56.888145 E65D579A64ECFE68C29D5F4EB25F5EA14D4E8D2F9DF626818B16BE401A7DC3A7FE 已用时间: 0.792(毫秒). 执行号:1804.
解密数据:
SQL> SELECT CFALGORITHMSDECRYPT(MEMO, 514, '仅供测试使用') FROM CJCD.SALES_ORDER WHERE ORDER_ID=3; 行号 CFALGORITHMSDECRYPT(MEMO,514,'仅供测试使用') ---------- -------------------------------------------------- 1 Note_HiIxlTubevebmogJTWIu 已用时间: 1.345(毫秒). 执行号:1805.
更新数据测试:
参考上面最后一版test_update_simple存储过程,
写一个新的存储过程test_update_simple,要求测试单条update SALES_ORDER 表的性能,
表 ORDER_ID=3行的MEMO列值是Note_HiIxlTubevebmogJTWIu,这个是解密后的值,当然,当前的MEMO列是被加密的,需要通过如下方式才能解密:
SELECT CFALGORITHMSDECRYPT(MEMO, 514, ‘仅供测试使用’) FROM CJCD.SALES_ORDER WHERE ORDER_ID=3;
要求更新为Note_HiIxlTubevebmogJTABC,然后再更新回Note_HiIxlTubevebmogJTWIu,反复重复100万次,每update一条,commit提交一次
CREATE OR REPLACE PROCEDURE test_update_simple AS -- 定义两个固定明文字符串 v_val_a_plain CONSTANT VARCHAR(50) := 'Note_HiIxlTubevebmogJTWIu'; v_val_b_plain CONSTANT VARCHAR(50) := 'Note_HiIxlTubevebmogJTABC'; -- 加密算法标识和密钥(与示例一致) v_alg CONSTANT INT := 514; v_key CONSTANT VARCHAR(50) := '仅供测试使用'; i INT; BEGIN -- 循环 10 万次 FOR i IN 1..100000 LOOP IF MOD(i, 2) = 1 THEN -- 奇数次:将 MEMO 从 v_val_a_plain 更新为 v_val_b_plain UPDATE SALES_ORDER SET MEMO = CFALGORITHMSENCRYPT(v_val_b_plain, v_alg, v_key) WHERE ORDER_ID = 3 AND CFALGORITHMSDECRYPT(MEMO, v_alg, v_key) = v_val_a_plain; ELSE -- 偶数次:将 MEMO 从 v_val_b_plain 更新回 v_val_a_plain UPDATE SALES_ORDER SET MEMO = CFALGORITHMSENCRYPT(v_val_a_plain, v_alg, v_key) WHERE ORDER_ID = 3 AND CFALGORITHMSDECRYPT(MEMO, v_alg, v_key) = v_val_b_plain; END IF; -- 每次更新后立即提交 COMMIT; END LOOP; END; / SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:21.452. 执行号:1808. SQL> CALL test_update_simple(); DMSQL 过程已成功完成 已用时间: 00:01:31.433. 执行号:1809.
查询数据:
SELECT COUNT(*) FROM ( SELECT CFALGORITHMSDECRYPT(SALES_PERSON,514, '仅供测试使用'),CFALGORITHMSDECRYPT(PRODUCT_NAME,514, '仅供测试使用'),SUM(amount) FROM SALES_ORDER GROUP BY CFALGORITHMSDECRYPT(SALES_PERSON,514, '仅供测试使用'),CFALGORITHMSDECRYPT(PRODUCT_NAME,514, '仅供测试使用') ) A; 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:25.042. 执行号:1811. 行号 COUNT(*) ---------- -------------------- 1 10000000 已用时间: 00:00:24.027. 执行号:1812.
1.5.6性能测试总结
总结:
存储加密后的存储膨胀:
透明加密:加密表空间:
1000万行数据,存储空间844MB,没有发生膨胀;
半透明加密:非加密表空间:
1000万行数据,存储空间1315MB,膨胀了471MB,膨胀率55.81%。
透明加密:非加密表空间:
1000万行数据,存储空间1122MB,膨胀了278MB,膨胀率32.94%。
非透明加密:非加密表空间:
1000万行数据,存储空间1776MB,膨胀了932MB,膨胀率110.43%。
存储加密后的性能损耗:
透明加密:加密表空间:
插入1000万行数据:耗时17.217秒,比非加密耗时延长10.348秒,性能损耗150.65%。
更新10万行数据,每1行提交1次:耗时83.674秒,比非加密耗时延长7.067秒,性能损耗9.22%
汇总查询,耗时10.32秒,比非加密耗时延长1.109秒,性能损耗12.34%。
半透明加密:非加密表空间,列加密:
插入1000万行数据:耗时27.003秒,比非加密耗时延长20.134秒,性能损耗293.11%。
更新10万行数据,每1行提交1次:耗时80.042秒,比非加密耗时延长3.435秒,性能损耗4.84%
汇总查询,耗时13.782秒,比非加密耗时延长4.571秒,性能损耗49.63%。
透明加密:非加密表空间,列加密:
插入1000万行数据:耗时24.695秒,比非加密耗时延长17.826秒,性能损耗259.51%。
更新10万行数据,每1行提交1次:耗时82.817秒,比非加密耗时延长6.21秒,性能损耗8.11%
汇总查询,耗时13.152秒,比非加密耗时延长3.941秒,性能损耗42.79%。
非透明加密:非加密表空间,列加密:
插入1000万行数据:耗时16.670秒,比非加密耗时延长9.835秒,性能损耗142.68%。
更新10万行数据,每1行提交1次:耗时86.442秒,比非加密耗时延长6.21秒,性能损耗12.84%
汇总查询,耗时24.535秒,比非加密耗时延长15.324秒,性能损耗166.37%。

2.参考链接:
https://eco.dameng.com/document/dm/zh-cn/pm/storage-encryption.html
欢迎关注我的公众号《 IT小Chen》