Oracle 11g SECUREFILES

Oracle 数据库 11g面向 DBA 和开发人员的重要新特性:SecureFiles:
1、SecureFiles:新 LOB 

了解如何使用新一代 LOB:SeureFiles。SecureFiles 集外部文件和数据库 LOB 方法的优点于一身,可以存储非结构化数据,允许加密、压缩、重复消除等等。 
数据库驻留 BLOBS 或 OS 文件 
您在 Oracle 数据库中存储什么?通常,您会以关系格式存储数据以便于映射到某些定义模式的类型,或者以客户姓名、帐户余额、状态代码等定义的数据类型存储数据。但是,以非结构化或半结构化格式存储信息的需求也日益增加。例如,照片、字处理文档、电子表格、XML 文件等等。这些类型的数据如何存储?  
 
通常有两种方法:这些数据作为 LOB 字段(BLOB 用于存储二进制数据,CLOB 用于存储字符数据)存储在数据库中,或者通过引用存储在数据库中的文件存储在 OS 文件中。 
 
每种方法都各具优缺点。OS 文件可以由 OS 和日志文件系统缓存以加速崩溃后的恢复。由于可进行压缩,因此 OS 文件占用的空间通常也比数据库中的数据要少。  
 
还有一些工具可以智能地识别文件模式并消除重复从而提高存储效率;但是 OS 文件位于数据库外部,因此数据库属性不适用于它们。这些文件不进行备份、细粒度安全性不适用于它们,此类文件不是事务的一部分 — 因此 Oracle 数据库固有的读取一致性等该概念不适用于它们。  
 
如果能集两种方法的优点于一身会怎样?Oracle 数据库 11g 中的 SecureFiles 为您提供了答案。SecureFiles 是数据库中一个全新的基础架构,可提供最佳的数据库驻留 LOB 和 OS 文件性能。让我们看一看这种方案的实现方式。(顺便说明的是,传统 LOB 仍然以 BasicFiles 格式提供。) 
 
2、实际示例 

通过一个简单的示例来介绍 SecureFiles 概念或许是一种最佳方式。假设您要开发一个合同管理系统,在该系统中您希望将所有合同的副本都放在一个表中。扫描的文档通常是 PDF 文件而非文本。某些可能是 MS Word 文档或者甚至是扫描的照片。这是 BLOB 的最佳使用案例,因为列必需能够支持二进制数据。 
 
通常,在 Oracle 数据库 11g 推出之前,您可能会按照以下方式定义表: 
 
create table contracts_basic 

        contract_id    number(12), 
        contract_name  varchar2(80), 
        file_size      number, 
        orig_file      blob 

tablespace users 
lob (orig_file) 

        tablespace users 
        enable storage in row 
        chunk 4096 
        pctversion 20 
        nocache 
        nologging 
); 

 
实际的文件以二进制格式存储在 ORIG_FILE 列中。各种参数指明在操作期间 LOB 不应缓存并记入日志,应按表行存储,块大小应为 4KB 并存储在表空间 USERS 中。由于您没有明确指定,因此 LOB 在 Oracle 数据库 11g 中以常规格式 (BasicFiles) 存储。  
如果您将 LOB 存储为 SecureFile,只需在创建表时放入一个子句 store as securefile,如下所示: 
 
create table contracts_sec  

        contract_id    number(12), 
        contract_name  varchar2(80), 
        file_size      number, 
        orig_file      blob 

tablespace users 
lob (orig_file) 
store as securefile 

        tablespace users 
        enable storage in row 
        chunk 4096 
        pctversion 20 
        nocache 
        nologging 


 
要创建 SecureFile LOB,您需要满足两个条件,而这两个条件都是默认设置,因此您可能已经满足。  
初始化参数 db_securefile 应设为 permitted(默认设置)。我会在后面部分说明该参数的作用。  
在其中创建 securefile 的表空间应启用自动段空间管理 (ASSM)。在 Oracle 数据库 11g 中,表空间创建的默认模式为 ASSM,因此该表空间可能已经这样设置。如果没有,则需要在一个新的 ASSM 表空间上创建 SecureFile。  
表创建完成后,您可以加载数据,方式与 11g 之前的常规 LOB (BasicFile) 相同。不需要更改应用程序,也不需要记住某些特殊的语法。  
 
下面是一个载入该表的小程序。 
 
declare 
    l_size      number;   
    l_file_ptr  bfile;   
    l_blob      blob;     
begin 
    l_file_ptr := bfilename('SECFILE', 'contract.pdf');  
    dbms_lob.fileopen(l_file_ptr);  
    l_size := dbms_lob.getlength(l_file_ptr);  
    for ctr in 1 .. 100 loop  
        insert into contracts_sec  
        (         
            contract_id,  
            contract_name,  
            file_size,   
            orig_file     
        )         
        values   
        (         
            ctr,         
            'Contract '||ctr,  
            null,         
            empty_blob()  
        )         
        returning orig_file into l_blob;   
        dbms_lob.loadfromfile(l_blob, l_file_ptr, l_size);  
    end loop;  
    commit;  
    dbms_lob.close(l_file_ptr);  
end; 

 
该程序将 contract.pdf 文件分 100 次载入表的 100 个行中。您应该已经为存储 contract.pdf 文件的 OS 目录定义了一个名为 SECFILE 的目录对象。下面的示例指明 contract.pdf 文件在 /opt/oracle 中的位置。 
SQL> create directory secfile for ’/opt/oracle’; 
 
将 LOB 存储为 SecureFile 后,您就可以获得很多能优化操作的特性。下面就是其中一些很有用的特性。  
3、重复消除 

重复消除可能是 SecureFiles 中最受欢迎的特性,它由于 OS 文件在某些高端文件系统中相对于数据库驻留 BLOB 的优势而倍受推崇。假设一个表有五个记录,每个记录各有一个 BLOB。其中三个 BLOB 是完全相同的。如果能够只存储该 BLOB 一次而在其他两个记录上只存储对该副本的引用将极大地减少空间消耗。这在 OS 在文件中是可行的,但在 Oracle 数据库 10g LOB 中则无法实现。但是如果使用 SecureFiles,只需通过一个称为重复消除的属性即可轻松搞定。可以在表创建时指定该属性,也可以在以后将其修改为: 
 
SQL> alter table contracts_sec 
  2  modify lob(orig_file) 
  3  (deduplicate) 
  4  / 
 
Table altered. 
 
使用重复消除后,数据库计算每行中各列的散列值并进行相互比较。如果有匹配的散列值,则存储该散列值而不是实际的 BLOB。新记录插入时会计算其散列值,如果其散列值与其他散列值匹配,则插入散列值;否则存储实际的值。  
 
下面,我们来看看进行重复消除过程后的空间节省情况。可以通过程序包 DBMS_SPACE 检查 LOB 段中的空间消耗。下面是一个显示空间消耗的程序: 
 
declare   
    l_segment_name          varchar2(30);  
    l_segment_size_blocks  number;  
    l_segment_size_bytes    number;  
    l_used_blocks          number;   
    l_used_bytes            number;   
    l_expired_blocks        number;   
    l_expired_bytes        number;   
    l_unexpired_blocks      number;   
    l_unexpired_bytes      number;   
 
begin 
    select segment_name  
    into l_segment_name  
    from dba_lobs  
    where table_name = 'CONTRACTS_SEC';  
        dbms_output.put_line('Segment Name=' || l_segment_name); 
 
    dbms_space.space_usage(  
        segment_owner          => 'ARUP',   
        segment_name            => l_segment_name,  
        segment_type            => 'LOB',  
        partition_name          => NULL,  
        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; 

 
该脚本显示 LOB 的各种与空间有关的统计信息。进行重复消除过程之前,输出如下:  
Segment Name=SYS_LOB0000070763C00004$$ 
segment_size_blocks    => 1072 
segment_size_bytes      => 8781824 
used_blocks            => 601 
used_bytes              => 4923392 
expired_blocks          => 448 
expired_bytes          => 3670016 
unexpired_blocks        => 0 
unexpired_bytes        => 0 
 
使用重复消除后:  
Segment Name=SYS_LOB0000070763C00004$$ 
segment_size_blocks    => 1456 
segment_size_bytes      => 11927552 
used_blocks            => 7 
used_bytes              => 57344 
expired_blocks          => 127 
expired_bytes          => 1040384 
unexpired_blocks        => 1296 
unexpired_bytes        => 10616832 
 
仅以上输出中的一个度量标准就足以说明问题:used_bytes。它显示了 LOB 列存储的字节数。使用重复消除之前,需要占用 4,923,392 字节或 5MB,但使用重复消除后,该值缩减为 57,344 字节或大约 57KB,差不多是原始值的 1%。这是因为重复消除过程发现了 100 个具相同值的行(回忆一下,我们将同一个值放到了所有行的 LOB 列中)。重复消除过程只保留了一行而使其他行成为指针。  
您也可以反向进行该重复消除过程: 
 
SQL> alter table contracts_sec 
  2  modify lob(orig_file) 
  3  (keep_duplicates) 
  4  / 
 
Table altered. 
 
之后,如果您再检查空间:  
Segment Name=SYS_LOB0000070763C00004$$ 
segment_size_blocks    => 1456 
segment_size_bytes      => 11927552 
used_blocks            => 601 
used_bytes              => 4923392 
expired_blocks          => 0 
expired_bytes          => 0 
unexpired_blocks        => 829 
unexpired_bytes        => 6791168 
 
您将发现 USED_BYTES 增加,变为大约 5MB 的原始值。 
 
4、压缩 

SecureFiles 的另一个特性是压缩。可以使用以下 SQL 压缩存储在 LOB 中的值:  

SQL> alter table contracts_sec 
  2  modify lob(orig_file) 
  3  (compress high) 
  4  / 
 
Table altered. 
 
现在,如果您运行空间查找 PL/SQL 块:  
Segment Name=SYS_LOB0000070763C00004$$ 
segment_size_blocks    => 1456 
segment_size_bytes      => 11927552 
used_blocks            => 201 
used_bytes              => 1646592 
expired_blocks          => 0 
expired_bytes          => 0 
unexpired_blocks        => 1229 
unexpired_bytes        => 10067968 
 
您将发现 used_bytes 这一度量标准由 5MB 降至现在的 1,646,592 或大约 1.5 MB。  
压缩与重复消除不同。压缩在每行的 LOB 列内部发生 — 每个 LOB 列单独压缩。在重复消除过程中,所有行都受到检查,列中的重复值将进行删除并替换为指针。如果您有两个完全不同的行,重复消除不会减少占用空间;但是压缩可以优化 LOB 值的空间。除了对表执行重复消除过程,您还可以对表进行压缩。  
 
由于压缩占用 CPU 循环,因此如果数据压缩量不大,可能并不值得进行压缩。例如,如果您有大量已经压缩过的 JPEG 照片,则进一步的压缩不会节省任何空间。但是,如果您有一个作为 CLOB 存储的 XML 文档,则压缩可以节省大量空间。SecureFiles 压缩自动检测数据是否可压缩并仅在压缩可以节省空间时占用 CPU 循环。  
 
Oracle Text 索引可以在压缩过的 SecureFiles LOB 上安装。较之文件系统中的压缩文件,这是在 Oracle 数据库中存储非结构化数据的主要好处。  
 
此外,请注意,LOB 压缩与表压缩无关。压缩表 CONTRACTS_SEC 并不会压缩 LOB。LOB 压缩仅在您执行上述 SQL 时才会发生。 
 
5、加密 

您可以对 SecureFiles 使用透明数据库加密,就像您将对任何列所做的一样。下面说明如何使用 AES 128 位加密对列 orig_file LOB 进行加密。  
 
alter table contracts_sec 
  modify lob(orig_file) 
  (encrypt using 'AES128') 

 
启用加密之前,您需要设置加密钱夹。(加密钱夹的完整描述可以在此 Oracle Magazine 文章中找到。)下面是总结的几个步骤:  
在 sqlnet.ora 中设置参数(如果尚未设置)以指定钱夹的位置:  
ENCRYPTION_WALLET_LOCATION=  
  (SOURCE=  
      (METHOD=FILE)  
      (METHOD_DATA=  
          (DIRECTORY= /opt/oracle/orawall) 
    )         
)       
 
目录 /opt/oracle/orawall 应该已经存在;如果不存在,则应该创建该目录。  
创建钱夹:  
alter system set encryption key authenticated by "mypass" 
 
这将创建口令为 mypass 的钱夹并将其打开。  
上述步骤只需执行一次。钱夹创建并打开后,只要数据库在运行它就会一直打开(除非人为关闭)。如果数据库重启,您需要通过以下语句打开钱夹:  
alter system set encryption wallet open identified by "mypass" 
 
当 SecureFile LOB 列得到加密后,该表所有行的列值都会得到加密。加密后,您不能在表中使用常规导出或导入;您需要使用数据泵。  
您可以查看视图 dba_encrypted_columns 了解哪些列已得到加密以及加密的方式。 
 
SQL> select table_name, column_name, encryption_alg 
  2  from dba_encrypted_columns 
  3  / 
 
TABLE_NAME                    COLUMN_NAME        ENCRYPTION_ALG 
------------------------------ ------------------ ----------------------------- 
CONTRACTS_SEC                  ORIG_FILE          AES 128 bits key 
 
6、缓存 

较之数据库驻留对象,在 OS 文件中存储非结构化数据的优势之一是缓存工具。文件可以在操作系统的文件缓冲区中进行缓存。数据库驻留对象还可以在数据库缓冲区缓存中进行缓存。但是,在某些情况下,缓存可能竟会损害性能。LOB 通常都很大(该术语大对象就是因此得名),如果它们进入缓冲区缓存,大多数其他的数据块将需要被推送出缓存以为要进来的 LOB 腾出空间。该 LOB 可能以后永远都不会使用,但是它进入缓冲区缓冲却会导致某些必需的数据块流出。因此,在大多数情况下,您可能希望对 LOB 禁用缓存。  
 
在针对 CONTRACTS_SEC 的示例脚本中,您使用了 nocache 子句来禁用缓存。要为 LOB 启用缓存,您可以对该表进行以下更改:  
 
alter table contracts_sec 
modify lob(orig_file) 
(cache) 

 
这将启用 LOB 缓存。注意该缓存只引用 LOB。表的其余部分放入缓冲区缓存,并遵循任何其他表的逻辑(无论该表上的 LOB 缓存如何设置)。  
缓存的优点是非常依赖于应用程序。在处理缩略图的应用程序中,使用缓存可能会提高性能。但是,对于大型文档或图像,最好关闭缓存。您可以通过 securefiles 进行控制。 
 
7、日志记录 

日志记录子句决定 LOB 中的数据更改如何记录到重做日志流中。与任何其他数据一样,默认设置为完全日志记录,但是由于 LOB 中的数据通常都很大,在某些情况下,您可能希望不进行日志记录。上述示例中的 NOLOGING 子句就可以实现该目的。 
 
SecureFiles 为该子句提供了另一个值 filesystem_like_logging,如下所示: 
 
create table contracts_sec_fs 

        contract_id    number(12), 
        contract_name  varchar2(80), 
        file_size      number, 
        orig_file      blob 

tablespace users 
lob (orig_file) 
store as securefile 

        tablespace users 
        enable storage in row 
        chunk 4096  
        pctversion 20 
        nocache 
        filesystem_like_logging 

 
注意以黑体显示的行,它将 LOB 元数据记录到重做日志中,而不是记录整个 LOB。这类似于文件系统。文件元数据记录到文件系统日志中。同样,SecureFiles 上的该子句会加速崩溃后的恢复。  
管理 
数据字典视图 DBA_LOBS 显示了数据库中 LOB 的属性(包括 SecureFiles)。下面是该视图的列:  
列名 
说明 
 
OWNER 
表的所有者 
 
TABLE_NAME 
表的名称 
 
COLUMN_NAME 
LOB 列的名称 
 
SEGMENT_NAME 
LOB 作为单独的段存储,由用户命名,默认为 SYS_LOB… 
 
TABLESPACE_NAME 
表空间的名称 
 
INDEX_NAME 
LOB 索引的名称 
 
CHUNK 
LOB 的块大小 
 
PCTVERSION 
在 SecureFiles 中忽略 
 
RETENTION 
如果 SecureFile LOB 进行了更新,以前的图像与任何其他数据库块一样保存在还原段中;但是与数据库块不同的是,您可以指定以前的图像保存多长时间(保留期)。 
 
FREEPOOLS 
对 SecureFiles 忽略 
 
CACHE 
SecureFile LOB 是否在缓冲池中缓冲(是/否),本文已说明 
 
LOGGING 
是否记录对 SecureFile LOB 进行的更改(是/否),本文已说明 
 
ENCRYPT 
SecureFile LOB 是否已加密(是/否),本文已说明 
 
COMPRESSION 
SecureFile LOB 是否已压缩(是/否),本文已说明 
 
DEDUPLICATION 
Securefile LOB 是否已进行重复消除(是/否),本文已说明 
 
IN_ROW 
LOB 是否按表行存储 
 
FORMAT 
LOB 是否与平台的字节顺序有关 
 
PARTITIONED 
LOB 是否在分区表上 
 
SECUREFILE 
LOB 是 SECUREFILE(是或否)还是 BASICFILE 
 
 
 
在分区表上,LOB 信息存储在视图 DBA_LOB_PARTITIONS 中。  
 
8、LOB 到 SecureFiles 的移植 

既然已经了解 SecureFiles 是多么有用,您可能希望对现有的表进行转换。最简单的方法是创建一个新表,载入旧表中的数据,然后重命名该表。(当然,这要求这些表在操作期间不可用。)另一种方法是使用 dbms_redefinition 程序包在线重新定义表,不影响可用性。  
 
我们通过一个示例来了解该过程。假设您希望移植原始表 CONTRACTS_BASIC 以存储为 SecureFiles。要实现该目的,执行以下步骤。 
 
确保您具有一个主键。如果没有,创建一个。  
alter table contracts_basic 
add constraint pk_contacts 
primary key (contract_id) 

 
构建新表。  
create table contracts_new 

contract_id    number(12), 
contract_name  varchar2(80), 
file_size      number, 
orig_file      BLOB 

lob (orig_file) 
store as securefile 
(nocache nologging) 

 
将列映射到新表。  
declare 
  l_col_mapping varchar2(1000); 
begin 
  l_col_mapping := 
    'contract_id contract_id , '|| 
    'contract_name contract_name , '|| 
    'file_size file_size, '|| 
    'orig_file orig_file'; 
    dbms_redefinition.start_redef_table 
      ('ARUP', 'CONTRACTS_BASIC', 'CONTRACTS_NEW', l_col_mapping); 
end; 

 
开始重新定义过程。  
declare 
  l_error_count pls_integer := 0; 
begin 
  dbms_redefinition.copy_table_dependents 
  ( 
      'ARUP', 'CONTRACTS_BASIC', 'CONTRACTS_NEW', 
      1, TRUE, TRUE, TRUE, FALSE, l_error_count 
  ); 
  dbms_output.put_line('Errors Occurred := ' ||  
      to_char(l_error_count)); 
end; 

 
这会将 CONTRACTS_BASIC 中的所有行复制到 CONTRACTS_NEW 中,因此,根据表的行数,该操作可能需要较长时间。  
完成重新定义过程。  
begin   
    dbms_redefinition.finish_redef_table 
      ('ARUP', 'CONTRACTS_BASIC', 'CONTRACTS_NEW'); 
end; 

 
确认表已得到转换。  
select securefile 
from dba_lobs 
where table_name = 'CONTRACTS_BASIC' 

 
SEC 
--- 
YES 
 
列显示 YES,表明列已转换为 SecureFiles。  
删除临时表 CONTRACTS_NEW。  
SQL> drop table contracts_new; 
 
Table dropped. 
 
您可以尝试在开始就启用并行 DML 以加快复制过程。下面说明如何在会话中启用并行 DML:  
alter session force parallel dml; 
 
9、初始化参数 

初始化参数 db_securefile 决定 SecureFiles 在数据库中的使用。下面是该参数的各种值及其效果:  
值 
效果 
 
PERMITTED 
默认值。该值指明可以在数据库中创建 SecureFile LOB。  
 
ALWAYS 
既然您已经知道了 SecureFiles 是多么有用,您可能希望确保所有 LOB 创建后就应该仅为 SecureFiles 而非默认的 BasicFiles(即使用户没有指定 securefile)。该参数值确保所有 LOB 默认情况下创建为 SecureFiles。记住,SecureFiles 需要 ASSM 表空间(在 11g 中为默认设置),因此如果您尝试在非 ASSM 表空间中创建 LOB,将出现错误。 
 
NEVER 
与 always 值相反。由于某种原因,您不喜欢 SecureFiles 并且不希望允许它在数据库中创建。即使使用 SecureFile 子句,该参数值仍然会将 LOB 创建为 BasicFile。当使用了 SecureFile 子句而 LOB 仍然创建为默认的 BasicFile 时,用户不会收到错误消息。 
 
IGNORE 
忽略 securefile 子句以及所有存储子句。 
 
 
 
 
结论 
SecureFiles 不仅是新一代 LOB,它们还为 LOB 带来了更多的价值,尤其是以前只能在文件系统领域中获得的特性。SecureFiles 可以进行加密以确保安全性,可以进行重复消除和压缩以提高存储效率,可以进行缓存(或不进行缓存)以加快访问(或节省缓冲池空间),可以按多个级别记录以减少崩溃后的平均恢复时间。引入 SecureFiles 后,您可以在数据库中存储更多的非结构化文档,而不会导致过多的开销,也不会失去 OS 文件系统提供的任何重要功能。  新 LOB

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值