SecureFile功能是oracle 11g中对大对象(LOB)存储格式的完全重新设计实现,原来的LOB存储格式现在通称为BASIXFILE,它仍然是默认的存储方法,但是SECURFILE关键字开启了新的存储方法,它允许加密、利用压缩节约空间和数据重复消除。
初始化参数
SecureFile功能在初始化参数COMPATIBLE设置我11.0.0.0.0或更高时可用。
DB_SECUREFILE初始化参数控制数据库对LOB存储格式的默认行为,允许的值有:
◆ALWAYS - 在ASSM表空间中的所有LOB对象以SecureFile LOB的格式创建,在非ASSM表空间中的所有LOB对象以BasicFile LOB的格式创建(除非明确地指出要以SecureFile格式创建),在没有指定选项的情况下,BasicFile存储格式选项被忽略,SecureFile默认存储格式选项被使用。
◆
FORCE
- 所有LOB对象都以SecureFile LOB格式创建,如果是在一个非ASSM表空间中创建LOB,会出现错误,在没有指定选项的情况下,BasicFile存储格式选项被忽略,SecureFile默认存储格式选项被使用。◆PERMITTED - 默认设置,当使用了SECUREFILE关键字时它允许SecureFile LOB存储格式,默认存储方法是BASICFILE。
◆NEVER - 不允许创建SecureFile LOB对象。
◆IGNORE - 防止创建SecureFile LOB,使用SecureFile存储选项时忽略所有错误。
这个参数是动态的,因此它可以使用ALTER
SYSTEM
命令设置。
sql>ALTERSYSTEM SETdb_securefile='FORCE';Systemaltered. sql>ALTERSYSTEMSETdb_securefile='PERMITTED'; Systemaltered. sql> |
下面的例子假设DB_SECUREFILE初始化参数设置为默认值PERMITTED。
创建SecureFile LOB
基础
SecureFile LOB通过在LOB存储子句后添加SECUREFILE关键字来创建,下面的代码显示创建了两个表,第一个使用的是原来的存储格式,第二个使用的是SecureFile存储格式。
CREATE TABLEbf_tab(idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASBASICFILE; INSERTINTObf_tabVALUES(1,'MyCLOB data');COMMIT;CREATETABLEsf_tab( idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASSECUREFILE; INSERTINTOsf_tabVALUES(1,'MyCLOBdata'); COMMIT; |
LOB重复消除
SecureFile的DEDUPLICATE选项允许在表或分区一级上的一个LOB内消除重复数据,正如你预料的那样,这个技术与预防重写导致系统开销增大,KEEP_DUPLICATE选项明确地阻止重复消除,下面的例子对比了普通的SecureFile和重复消除SecureFile的空间使用情况。
CREATE TABLEkeep_duplicates_tab(idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASSECUREFILEkeepdup_lob( KEEP_DUPLICATES ); CREATETABLEdeduplicate_tab( idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASSECUREFILEdedup_lob( DEDUPLICATE ); DECLARE l_clobCLOB:=RPAD('X',10000,'X'); BEGIN FORiIN1..1000 LOOPINSERTINTOkeep_duplicates_tabVALUES(i,l_clob); ENDLOOP; COMMIT;FORiIN1..1000LOOP INSERTINTOdeduplicate_tabVALUES(i,l_clob); ENDLOOP; COMMIT; END; / EXECDBMS_STATS.gather_table_stats(USER,'keep_duplicates_tab'); EXECDBMS_STATS.gather_table_stats(USER,'deduplicate_tab'); COLUMNsegment_name FORMATA30SELECTsegment_name,bytes FROMuser_segments WHEREsegment_nameIN('KEEPDUP_LOB','DEDUP_LOB'); SEGMENT_NAMEBYTES ---------------------------------------- DEDUP_LOB262144 KEEPDUP_LOB19267584 2rowsselected. sql> |
注意重复消除段要小很多,空间节约依赖于LOB段内的重复程度,重复模式可以使用ALTER TABLE命令进行重新设置。ALTER
TABLE
deduplicate_tabMODIFYLOB(clob_data)(KEEP_DUPLICATES
);
EXECDBMS_STATS.gather_table_stats(USER,'DEDUP_LOB');
SEGMENT_NAMEBYTES
----------------------------------------
DEDUP_LOB76808192
KEEPDUP_LOB68091904
2rowsselected.
sql>
LOB压缩
SecureFile的COMPRESS选项在表或分区一级上开启了对LOB内容的压缩,使用关键字MEDIUM和HIGH表示压缩的等级,如果没有指定压缩等级,就默认为MEDIUM,对LOB内容进行压缩会增加系统开销,因此使用高等级的压缩可能会对系统性能产生不良影响,SecureFile LOB的压缩功能不影响表压缩,反之亦然,下面的例子对比了使用普通的SecureFile LOB和启用压缩功能的SecureFile LOB的空间利用情况。
LOOPINSERTINTOnocompress_tabVALUES(i,l_clob); ENDLOOP; COMMIT;FORiIN1..1000LOOP INSERTINTOcompress_tabVALUES(i,l_clob); ENDLOOP; |
TABLE
deduplicate_tabMODIFYLOB(clob_data)(KEEP_DUPLICATES
);
EXECDBMS_STATS.gather_table_stats(USER,l_clob);
ENDLOOP; COMMIT;
END;
/
EXECDBMS_STATS.gather_table_stats(USER,'nocompress_tab');
EXECDBMS_STATS.gather_table_stats(USER,'compress_tab');
COLUMNsegment_nameFORMATA30
SELECTsegment_name,bytes
FROMuser_segments
WHEREsegment_nameIN('COMPRESS_LOB','NOCOMPRESS_LOB');
SEGMENT_NAMEBYTES
----------------------------------------
COMPRESS_LOB131072
NOCOMPRESS_LOB71565312
2rowsselected.
sql>
我们可以看到压缩的LOB段比没有压缩的LOB段明显要小得多,空间节约的程度依赖于LOB段数据的存储类型。
可以使用ALTER
TABLE
命令重新设置压缩模式。
ALTERTABLEcompress_tabMODIFYLOB(clob_data)( NOCOMPRESS ); EXECDBMS_STATS.gather_table_stats(USER,'compress_tab'); COLUMNsegment_nameFORMATA30 SELECTsegment_name,'NOCOMPRESS_LOB'); SEGMENT_NAMEBYTES ---------------------------------------- COMPRESS_LOB76808192 NOCOMPRESS_LOB71630848 2rowsselected. sql> |
LOB加密
SecureFile LOB的加密功能依赖于钱夹或硬件安全模型(HSM)掌管加密密钥,钱夹设置与透明数据加密(TDE)和表空间加密描述的一样,因此在尝试下面的例子前先完成那两个实验。
SecureFile的ENCRYPT选项执行块级别的LOB内容加密,一个可选的USING子句定义了使用哪种加密算法(3DES168,AES128,AES192,或AES256),默认使用AES192算法,NO
SALT
选项对于SecureFile加密不可用,加密是应用在每一列上的,因此它会影响所有使用LOB的分区,DECRPT选项用于明确地阻止加密,下面的例子显示了使用加密的SecureFile LOB数据类型创建表。
CREATETABLEencrypt_tab( idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASSECUREFILEencrypt_lob( ENCRYPTUSING'AES256' ); |
ALTER
TABLE
命令可以用于加密或解密现有的列,要切换加密算法你必须使用REKEY选项。
ALTERTABLEencrypt_tabMODIFY( clob_dataCLOB DECRYPT); ALTERTABLEencrypt_tabMODIFY( clob_dataCLOBENCRYPTUSING'3DES168' ); ALTERTABLEencrypt_tabREKEYUSING'AES192'; |
加密是不受原来的导入导出工具或表空间传输支持的,因此必须使用数据泵导入导出工具来传输数据。
LOB缓存和日志
BasicFile和SecureFile LOB共享了部分基础的缓存和日志选项,常见的缓存选项有:
◆
CACHE
- LOB数据被放在缓冲区中。◆CACHE READES - 仅读取LOB数据过程中它放在缓冲区中,写操作时不放进去。
◆NOCACHE - LOB数据不放在缓冲区中,这是BasicFile和SecureFile LOB的默认值。
基本的日志选项有:
◆LOGGING - 创建和修改LOB时产生完全重做日志,这是默认设置。
◆NOLOGGING - 操作不记录在重做日志中,因此不能恢复,在首次创建和巨大的载入过程中有用。
而且,SecureFile LOB还有一个日志选项FILESYSTEM_LIKE_LOGGING,只记录元数据,在出现故障后仍然允许段的恢复。
CACHE选项意味着LOGGING,因此你不能将CACHE与NOLOGGING或FILESYSTEM_LIKE_LOGGING合在一起使用。
下面的代码显示了一个在表创建过程中和创建后明确设置了缓存和日志选项的例子。
CREATETABLEcaching_and_logging_tab( idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASSECUREFILE( NOCACHE FILESYSTEM_LIKE_LOGGING ); ALTERTABLEcaching_and_logging_tabMODIFYLOB(clob_data)( CACHE ); PL/sqlAPI |
DBMS_LOB包用于访问BasicFile和SecureFile LOB,SETOPTIONS存储过程和GETOPTIONS函数允许在每个LOB列上设置压缩、加密和重复消除选项。
CREATE TABLEsecurefile_tab(idNUMBER, clob_dataCLOB ) LOB(clob_data)STOREASSECUREFILEsecurefile_lob( encrypt compress ); INSERTINTOsecurefile_tabVALUES(1,'ONE'); INSERTINTOsecurefile_tabVALUES(2,'TWO'); COMMIT;SETSERVEROUTPUTONDECLARE l_clobCLOB; BEGIN SELECTclob_data INTOl_clob FROMsecurefile_tab WHEREid=1 FORUPDATE; DBMS_OUTPUT.put_line(' Compression:'||DBMS_LOB.getoptions(l_clob,DBMS_LOB.opt_compress));DBMS_OUTPUT.put_line(' Encryption:'||DBMS_LOB.getoptions(l_clob,DBMS_LOB.opt_encrypt));DBMS_OUTPUT.put_line('Deduplication:'||DBMS_LOB.getoptions(l_clob,DBMS_LOB.opt_deduplicate)); ROLLBACK;END; / |
DBMS_SPACE包括SPACE_USAGE存储过程,它返回有关所有LOB段中的LOB磁盘空间的消耗情况,这个存储过程也可以用于ASSM表空间。
|
segment_type=>'LOB',
segment_size_blocks=>l_segment_size_blocks,
segment_size_bytes=>l_segment_size_bytes,
used_blocks=>l_used_blocks,
used_bytes=>l_used_bytes,
expired_blocks=>l_expired_blocks,
expired_bytes=>l_expired_bytes,
unexpired_blocks=>l_unexpired_blocks,
unexpired_bytes=>l_unexpired_bytes);
DBMS_OUTPUT.put_line('segment_size_blocks:'||l_segment_size_blocks);
DBMS_OUTPUT.put_line('segment_size_bytes:'||l_segment_size_bytes);
DBMS_OUTPUT.put_line('used_blocks:'||l_used_blocks);
DBMS_OUTPUT.put_line('used_bytes:'||l_used_bytes);
DBMS_OUTPUT.put_line('expired_blocks:'||l_expired_blocks);
DBMS_OUTPUT.put_line('expired_bytes:'||l_expired_bytes);
DBMS_OUTPUT.put_line('unexpired_blocks:'||l_unexpired_blocks);
DBMS_OUTPUT.put_line('unexpired_bytes:'||l_unexpired_bytes);
END;
/
迁移到SecureFile
目前还没有方法可以自动将一个BasicFile列迁移到SecureFile LOB列,相反,你必须使用下面的方法手动转换数据:
◆CREATE
TABLE
... AS SELECT ...◆INSERT INTO ... SELECT ...
◆表在线重定义
◆导出/导入
◆创建一个新列,用原始列的值更新新列,然后删除旧列
◆创建一个新列,用原始列的值更新新列,重命名表,用原始表名创建一个仅引用新列的视图
除导出/导入方法外,在转换包含有大量数据的LOB时,所有选项都需要注意磁盘空间的数量。
oralce流目前不支持SecureFile,因此要避免迁移使用了流的LOB对象。