Logmnr在Oracle 9i以后做了众多的改进,如可以不需要build flat文本文件就可以分析日志了,也就表示可以不需要修改参数utl_file_dir就可以分析日志了,避免了修改参数utl_file_dir导致的重起数据库问题。另外也开始支持把字典信息build到联机日志中,在异地分析归档日志。
在flashback也不能帮上忙的时候,logmnr却是非常有用的。因为只要误操作时期的归档日志存在,就可以通过归档日志来恢复误删除(delete)的数据。
如果在Oracle 9i以上,采用在本地的在线数据字典分析归档日志,就这么简单:
- Piner@9iR2>exec -
- sys.dbms_logmnr.add_logfile(LogFileName=>'/archive_log/archive/1_9.arc',-
- options => dbms_logmnr.new);
- PL/SQL procedure successfully completed.
-
- Piner@9iR2>exec sys.dbms_logmnr.start_logmnr( -
- Options => sys.dbms_logmnr.dict_from_online_catalog);
- PL/SQL procedure successfully completed.
可以看到,在线分析其实就只需要这两步,添加日志并分析日志。注意以上OPTIONS => DBMS_LOGMNR.NEW,表示添加第一个日志,如需要另外添加更多的日志,可以用如下方式即可。
- Piner@9iR2>exec sys.dbms_logmnr.add_logfile(LogFileName=>'/archive_log/archive/1_10.arc');
如果日志分析完成,可以把需要的信息保存到临时表,如
- Piner@9iR2>create table tmp_logmnr as
- 2 select operation,sql_redo,sql_undo from v$logmnr_contents
- 3 where seg_name='TEST';
然后,终止日志分析过程。
- Piner@9iR2>exec sys.dbms_logmnr.end_logmnr
对于临时表中的SQL_UNDO,可以选择性的恢复,如采用如下的脚本来恢复,这里为了减少阻塞,每1000条提交一次。另外,需要注意的是,SQL_UNDO中的分号,如果想用动态SQL来执行的话,是需要去掉的。
- declare
- mysql varchar2(4000);
- num number :=0;
- begin
- for c_tmp in (select sql_undo from tmp_logmnr where operation = 'DELETE') loop
- --去掉语句中的分号,这里假定只有语句结尾有分号,语句中间并没有分号。
- --如果语句中也有分号,则可以考虑替换语句结尾的;'(分号单引号)为'(单引号)。
- mysql := replace(c_tmp.sql_undo,';','');
- execute immediate mysql;
- num := num + 1;
- if mod(num,1000)=0 then
- commit;
- end if;
- end loop;
- commit;
- exception
- when others then
- --异常处理
- end;
以上的PL/SQL代码其实还可以加强,如恢复成功一条,就设置状态值为1,否则,设置状态值为-1,方便跟踪那些记录恢复成功,哪些记录恢复失败了。
另外,需要注意的是,在Oracle 10g以下,LOGMNR的临时表v$logmnr_contents,使用的是system表空间,在Oracle 10g以后改为sysaux表空间。可以使用如下的命令,更改logmnr的特定表空间,防止system表空间出现空间不够。
- Piner@9iR2>exec sys.dbms_logmnr_d.set_tablespace('USERS');
从Oracle 9i开始,oracle standby就开始可以实现“滚动”升级,如升级一个小的补丁(patch)或者是一个补丁集(patch set),如图:
如果升级小的补丁,并不涉及到数据字典的升级,这个方式问题不大,但是,一旦涉及到升级数据字典,就存在一些问题了
1、在oracle 10gR2以前,如果存在一个或多个物理standby,因为物理Standby是只读的,只有升级软件的时候是可以在线升级的,升级standby数据字典的时候必须要switch over或者是failover之后,在停机时间来进行,这个过程耗费的时间可能也比较长。
2、在oracle 11gR1以前,主备库之间最多只能是跨小版本的补丁集,而不能是主版本的跨越,如9i到10g的standby,导致这个升级的功能也很有限。
至于问题1,在Oracle 10gR2以后,推出了一个全新的方法,如果主库存在一个或者多个物理Standby,可以先把其中一个物理Standby转换为逻辑Standby,执行升级操作,升级完成以后再转换为物理Standby。这个过程不会影响到其它的物理standby,完全可以平滑进行,这样的话,连升级数据字典的时间也可以在线完成了。
至于问题2,在Oracle 11gR1以后,可以跨大版本做Standby,如从Oracle 10gR2到Oracle 11g,所以,如果Standby升级到11g,依然可以接受Oracle 10gR2的日志,并应用,这个对大版本的数据库升级非常有用。
所以,有了以上的一些技术,就可以完全实现在线安装新版本的软件,在线升级了,整个升级过程最终仅仅是Standby切换的时间那么长而已。
最后,如果再结合如下2个技术点,整个过程就非常完美了
1、SQL重演(SQL replay)技术,可以在升级以后的standby目标数据库上,运行主库的完全的负载压力,看看目标数据库是否符合现在负载压力的要求,特别是SQL语句的执行计划,在新的数据库版本中,是否有所变化。
2、结合前面结束到的falsh database或者是slapshot database技术,可以在升级以后的standby目标数据库上做完压力测试,或者是SQL replay之后,继续回到Standby恢复状态,对整个系统不造成任何影响。
上一篇说了oracle 11g中,add column的时候,其实并没有真正去修改以前的块,Oracle只不过采用了类似nvl(null,default value)的方法来处理这个问题,但是,如果再次去掉这个默认值,那会怎么样呢?
下面将做一个简单的实验,来说明这个问题,这里的实验,完全接着上一篇的实验,所以,具体情况,还是请先参考上一篇:Oracle 11g增加列,并带默认值的新特性
上一篇说到了,新添加的列,如果指定了默认值,并没有修改以前的块,读取以前的行的时候,可能发生一个转换过程。但是,如果对于已经设置过默认值的情况,插入新值的时候,这么默认值是怎么处理的呢:
之前的情况:
- Piner@11gR1> desc test;
- Name Type Nullable Default Comments
- ---- ---------- -------- ------- --------
- A INTEGER Y
- FLAG CHAR(2000) Y 0
-
- Piner@11gR1>exec show_space('TEST');
- Total Blocks............................8
- Total Bytes.............................65536
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................83745
- Last Used Block.........................8
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>select count(*) from test;
- COUNT(*)
- ----------
- 1000
插入新记录:
- Piner@11gR1>begin
- 2 for i in 1..1000 loop
- 3 insert into test(a) values('1');
- 4 end loop;
- 5 commit;
- 6 end;
- 7 /
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>exec show_space('TEST');
- Total Blocks............................384
- Total Bytes.............................3145728
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................90889
- Last Used Block.........................128
- PL/SQL procedure successfully completed.
可以看到,新插入的1000条记录,块的个数发生了非常大的变化,证明了在新的记录中,Oracle实际上是真正把默认值添加到块中去了。但是,只有以前的记录依然是没有值的,需要靠转换来完成。
现在有2000条记录,是分2次插入进去的,这个时候,如果去掉默认值,会发生什么情况?是一半有值,一半没有值,还是都有值呢?我们再看:
- Piner@11gR1>alter table test modify flag default null null;
- Table altered.
-
- Piner@11gR1>select count(*) from test where flag is null;
- COUNT(*)
- ----------
- 0
-
- Piner@11gR1>exec show_space('TEST');
- Total Blocks............................384
- Total Bytes.............................3145728
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................90889
- Last Used Block.........................128
- PL/SQL procedure successfully completed.
可以看到,虽然解除了默认值,块的个数也没有任何变化,以前的记录依然是没有真实的写入任何数值到块中的,但是,Oracle 依然能把以前的默认值显示出来,因为is null查不出来任何记录,而且查询记录就可以看到实际的值就是以前的默认值。
最后,再增加1000条记录,这个时候可以发现,因为去掉了默认值,现在在另外一个列上,写入的为null。
- Piner@11gR1>begin
- 2 for i in 1..1000 loop
- 3 insert into test(a) values(1);
- 4 end loop;
- 5 commit;
- 6 end;
- 7 /
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>exec show_space('TEST');
- Total Blocks............................384
- Total Bytes.............................3145728
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................90889
- Last Used Block.........................128
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>select count(*) from test where flag is null;
- COUNT(*)
- ----------
- 1000
所以,对于整个过程分析下来,可以这么认为,oracle在add column default的时候,只是记录了一个标记,标记为这个点之前的所有块,如果是NULL的话,是需要转换的,反之取出实际的值。而这个点之后的块,就是按照实际的值来处理,如果中途反复修改,则以修改为准。
因为add column default,对于一个列,最多发生一次,所以,一个列只记录一个参照点即可。
但是,对于这个特性,有人想问,如果想保持以前的值为null,不要强行转换,但是,又想把新增加的列设置一个默认值,怎么办?其实也很简单,跟以前一样,分2步走即可,这样的话,以前的值还是null,新的值将为默认值。
- Piner@11gR1>alter table table_name add field_name number;
- Piner@11gR1>alter table table_name modify field_name default 0;
老和尚在他的blog中描述了了这个问题,我这里做一个详细的测试来说明这个问题。
在oracle 11g以前,如果需要在一个表中执行类似如下的命令,而且这个表本身已经有很多数据,那么,这个操作将可能花费很长的时间,并且可能阻塞应用:
- SQL>alter table table_name add field_name number default 0 not null;
因为这个操作需要修改以前所有的行,并把他们都修改为默认值,如以上的0。但是,这个情况在oracle 11g中有了巨大的改变,oracle 11g中,如果对一个表增加一个列,并带有默认值,Oracle并没有真实的去修改以前的列,只不过通过查询的时候,采用类似NVL(null,新值)的方法转换一下,让以前的列看起来象有值一样。
这个过程在select 的时候就转换好了,所以,对于使用者看来,他们是有值的,这个细小的改动将大大减少这个语句的执行时间,使得这样的语句在oracle 11g中不会引起任何阻塞,更不会影响性能了。
下面看一个简单的对比说明:
首先是Oracle 10g的测试
- Piner@10gR2>create table test(a int);
- Table created.
-
- Piner@10gR2>begin
- 2 for i in 1..1000 loop
- 3 insert into test values('1');
- 4 end loop;
- 5 commit;
- 6 end;
- 7 /
- PL/SQL procedure successfully completed.
-
- Piner@10gR2>set serveroutput on
- Piner@10gR2>exec show_space('TEST');
- Total Blocks............................8
- Total Bytes.............................65536
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................135641
- Last Used Block.........................8
- PL/SQL procedure successfully completed.
-
-
- Piner@10gR2>alter table test add flag char(2000) default 1 not null;
- Table altered.
-
- Piner@10gR2>exec show_space('TEST');
- Total Blocks............................384
- Total Bytes.............................3145728
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................134409
- Last Used Block.........................128
- PL/SQL procedure successfully completed.
-
- Piner@10gR2>select count(*) from test where flag is null;
-
- COUNT(*)
- ----------
- 0
可以看到的是,在增加默认值的列以后,该表的使用空间发生了巨大的变化,也证明数据库修改了以前的所有的块中的数据,让他们都生效。
以下是Oracle 11g的操作
- Piner@11gR1>create table test(a int);
- Table created.
-
- Piner@11gR1>begin
- 2 for i in 1..1000 loop
- 3 insert into test values('1');
- 4 end loop;
- 5 commit;
- 6 end;
- 7 /
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>set serveroutput on
- Piner@11gR1>exec show_space('TEST');
- Total Blocks............................8
- Total Bytes.............................65536
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................83745
- Last Used Block.........................8
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>alter table test add flag char(2000) default 1 not null;
- Table altered.
-
- Piner@11gR1>exec show_space('TEST');
- Total Blocks............................8
- Total Bytes.............................65536
- Unused Blocks...........................0
- Unused Bytes............................0
- Last Used Ext FileId....................4
- Last Used Ext BlockId...................83745
- Last Used Block.........................8
- PL/SQL procedure successfully completed.
-
- Piner@11gR1>select count(*) from test where flag is null;
-
- COUNT(*)
- ----------
- 0
这里可以看到,同样的记录,做了同样的操作,增加新列,并设置默认值以后,表的使用空间没有发生任何变化,也同样证明了Oracle没有修改以前的块中的数据。
这里的例子只有1000条记录,主要是为了体现了空间的变化。如果是几是万条,或者几百万条以上的表,同样的操作,oracle 11g是马上就结束了,不会有任何影响,而oracle 10g可能需要非常长的时间,这个时间表是被锁住的,不能执行任何DML操作,对于写频繁的应用来说,将会导致应用的阻塞。
没有什么特别的地方,记录一下,方便查找。
第一个用户Piner:
创建一个测试表
- SQL> create table test as select * from dba_objects;
创建一个测试索引
- SQL> create index ind_test on test(object_id);
如果是Oracle 10g以上,索引创建完成,就自带统计信息了。
创建一个表,存放export出来的统计信息
- SQL> exec dbms_stats.create_stat_table(ownname => 'Piner', stattab => 'STAT_AT', tblspace => 'SYSTEM');
刚创建完成,记录数为0
- SQL> select count(*) from STAT_AT;
-
- COUNT(*)
- ----------
- 0
收集表的统计信息
- SQL>exec dbms_stats.gather_table_stats(ownname=>'PINER',tabname=>'TEST',estimate_percent => 100,method_opt=> 'FOR ALL INDEXED COLUMNS');
如果是oracle 10g以下,如9i,以上的分析是没有分析到索引的,可以在上面的分析中增加cacade=>true,或者是单独分析索引。
- SQL>exec dbms_stats.gather_index_stats(ownname=>'PINER',indname=>'IND_TEST',estimate_percent=>100);
我们导出统计信息
- SQL>exec dbms_stats.export_table_stats(ownname=>'PINER', tabname=>'TEST', stattab=> 'STAT_AT');
-
- SQL> select count(*) from STAT_AT;
-
- COUNT(*)
- ----------
- 78
切换到另外一个用户test
- SQL> create table test as select * from dba_objects;
-
- Table created.
-
- SQL> create index ind_test on test(object_id);
-
- Index created.
-
- SQL> create table STAT as select * from piner.STAT_AT;
-
- Table created.
如果直接执行当前的用户与表名,可以执行成功,但是,没有统计数据导入,需要把原来的导出用户更新成导入用户。
- SQL>exec dbms_stats.import_table_stats(ownname=>'TEST', tabname=>'TEST', stattab => 'STAT');
-
- SQL>update stat set c5='TEST' where c5='PINER'
-
- SQL>commit;
-
- SQL>exec dbms_stats.import_table_stats(ownname=>'TEST', tabname=>'TEST', stattab => 'STAT');
然后再导入成功,导入信息包括表统计,索引统计信息,列的分析信息
kamus在他的blog 10gRAC培训 - 2 and last。说到了这个cpu time,具体可以看正文以及下面我与他的留言,他的意思其实就是:
CPU Time相对于其它等待事件,应当先忽略CPU Time,处理其它等待事件。而且cpu time高一般代表是好事情,因为系统并没有把时间耗费在Wait上。Elapsed Time = CPU Time + Wait Time,所以甚至我们可以说CPU Time越高越好。
不是说他的不对,只是比较觉得这句话太容易误导别人,所以,给一些补充建议,我同意如果有很明显的其它事件,而cpu time不明显的时候,可以优先处理其它事件。但是,还有以下2个地方需要注意:
1、cpu time高一般代表系统的逻辑读大,或者是高计算型的东西,如case函数,decode函数,自定义的计算类型函数等等,把cpu给耗光了,但是这个时候可能根本没有其它等待事件。这样是否证明这个系统很好呢?很可能是,非常不好,因为他很有可能没有必要有这么多的逻辑多,或者是,没有必要有这么多的cpu密集型计算就可以完成的任务,现在消耗这么CPU Time就是不正常的,很容易导致系统负载异常。
2、至于wait time,比如OLTP环境上最典型的db file sequential read引起的等待,是因为发生了物理io而引起的,而很多时候,物理读是随逻辑读增加而增加的,而逻辑读可能会导致cpu time高,也就是说,cpu time与wait time一般是同时增加的。特别是比较高访问量,大数据量,大SGA的系统,逻辑读与物理读都比较高,除了cpu time与db file sequential read,可能不会有很明显的其它等待事件,而优化的结果可能是cpu time与wait time同时减少。
既然说到了db file sequential read,也解释一下这个事件,与cpu time一样,很多时候说明系统是比较正常的,一个优化非常良好的系统,很可能第一个等待事件就是它。因为没有一个系统,不会发生任何物理IO,既然有物理IO,当然db file sequential read就是最好的了,一般表示读数据正常。同样的理由,db file sequential read大了,也可能预兆系统有不该有的物理读发生了。
如一个看起来很正常的sql语句,单个语句效率看起来并不差,执行时间已经小于0.01秒。假定原来逻辑读每个语句平均是100个,物理读平均10个,执行次数每小时50万次,优化完成以后,逻辑读降低为平均50个,物理读平均5个,那么,每小时降低的逻辑读总量就是50*50w=2500w个,降低的物理读为5*50w=250w个。那么再假定每个cpu每秒处理100000个逻辑读就达到了极限,每个物理读需要等待8ms,那么,就可以减少约2500w/100000*3600=7%的CPU使用率(单CPU),可以减少250w*8ms=20000秒的总io wait time。
同理,如果能采用同样的方法,减少执行次数从每小时50w到每小时25w,则收到的效果是一样的。
评价这个cpu time与db file sequential read是否正常,需要很多调优的经验,不过,需要记住的是,任何情况下,不要绝对的说好还是不好。最好的方式就是从statspack或者是awr上看看,排在cpu time,或者是物理读top的语句,他们是否应当有这么大的消耗,他们是否应当执行这么多的次数。
我们先看一个具体的例子
会话1,创建一个简单表,并在上面创建一个存储过程:
- 11gR1 Piner>create table test (a int);
-
- Table created.
-
- 11gR1 Piner>create or replace procedure sp_test
- 2 as
- 3 num number;
- 4 begin
- 5 select count(*) into num from test;
- 6 end;
- 7 /
-
- 11gR1 Piner>select object_name,status from user_objects where object_name='SP_TEST';
-
- OBJECT_NAME STATUS
- ------------------------------ -------
- SP_TEST VALID
同样的会话,我们插入一条记录,查看锁状态:
- 11gR1 Piner>insert into test values(1);
-
- 1 row created.
-
- 11gR1 Piner>SELECT USERENV('SID') FROM DUAL;
-
- USERENV('SID')
- --------------
- 118
-
- 11gR1 Piner>select sid,id1,id2,type,lmode,request from v$lock
- 2 where sid = 118;
-
- SID ID1 ID2 TY LMODE REQUEST
- ---------- ---------- ---------- -- ---------- ----------
- 118 99 0 AE 4 0
- 118 71091 0 TM 3 0
- 118 524292 679 TX 6 0
可以看到,这里对比以前的版本,多了一个类型为AE的锁。
然后,我们在另外一个会话做另外的操作
会话2:增加列
- SQL> alter table test add b int;
-
- Table altered.
-
- SQL> alter table test drop column b;
- alter table test drop column b
- *
- ERROR at line 1:
- ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
-
- 11gR1 Piner>select object_name,status from user_objects where object_name='SP_TEST';
-
- OBJECT_NAME STATUS
- ------------------------------ -------
- SP_TEST VALID
可以看到,列增加成功,并没有任何阻塞,但是,drop列是阻塞的。是因为add新列并不影响正在执行的dml,但是drop老列却是可能影响到正在执行的DML的。
也可以看到,增加列的过程完成以后,存储过程并不失效。这个是很好的一个特性,只要不让存储过程错误,就不会使得存储过程INVALID,减少了DDL引发的library cache pin可能导致的系统异常。
我们另外看看oracle 11g的一个ddl timeout参数,在会话2上修改此参数,并重新执行刚才的drop列的命令。
- SQL> show parameter ddl_lock_timeout;
-
- NAME_COL_PLUS_SHOW_PARAM TYPE VALUE_COL_PLUS_SHOW_PARAM
- ------------------------------ ----------- --------------------------
- ddl_lock_timeout integer 0
-
- SQL> alter system set ddl_lock_timeout = 10;
-
- System altered.
-
- SQL> set timing on
- SQL> alter table test drop column b;
- alter table test drop column b
- *
- ERROR at line 1:
- ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
-
- Elapsed: 00:00:10.00
这里的ddl_lock_timeout表示ddl会等待设置的值(单位为秒),这个是很有用的,比如在一个更新很频繁的表上面,适当的等待可以让ddl执行成功,以前dcba专门写了一个循环来模拟这个等待,现在,终于有这个参数了。
可以看到,正好等待10s左右
现在,会话1,我们提交该事务
- 11gR1 Piner>commit;
-
- Commit complete.
会话2,drop终于可以成功了
- SQL> alter table test drop column b;
-
- Table altered.
我们再查看存储过程的状态
- 11gR1 Piner>select object_name,status from user_objects where object_name='SP_TEST';
-
- OBJECT_NAME STATUS
- ------------------------------ -------
- SP_TEST VALID
整个简单测试到此完成,大家看到了几处跟以前10g不一样的地方?可以看到的是,oracle在一些细节的地方,处理的越来越好了。
如果在几年以前,谈起数据库的安全,估计没有多少人会理解其重要性。但是,现在不同了,因为更多敏感信息的泄露或篡改而导致身份窃取和财务违规的现象,让企业,特别是上市公司,不得不重视安全问题。
目前,减轻内部安全威胁的呼声越来越高,加之美国萨班法案(Sarbanes-Oxley)、美国HIPAA法案(Health Insurance Portability and Accountability Act)、日本个人信息保护法案、欧盟隐私和电子通信指令等法规和隐私保护指令的不断出台,保护数据免受未授权访问已经成为当务之急。
为了解决这个问题,oracle去年推出了Oracle Database Vault,一个从数据库层面上解决安全问题的产品。 Oracle Database Vault帮助客户保护敏感信息免遭内部威胁,并实施分责指令,要求敏感任务由多人完成。但是数据库至少是9208或者是10.2.3,在oracle 11g有进一步的加强。database vault可通过下列方法解决一些最为常见的安全问题和内部威胁:
·限制特权DBA,如sysdab以及有select any table的授权用户访问应用程序数据。
·防止应用程序 DBA 操纵数据库和访问其他应用程序。
·更好的控制何人、何时、何地可以访问应用程序。
Oracle Database Vault体现出来的三权为:
管理dba:通常是sysdba,如果安装并激活了database vault,sysdba的权限将大大减少,操作系统认证也将失效,没有alter user等等特权,不能查看由Oracle Database Vault保护起来的业务数据。举一个例子,你有一个业务用户叫HR,已经被database vault给保护起来了,你就是有再大的查看权限,如select any table,你也查看不了HR用户下的数据。所以,管理dba的作用就是启动关闭数据库,管理数据文件,管理表空间等等。
应用或者是开发dba:因为不能通过OS认证登陆数据库,所以,他们在没有sys等特权用户的密码的情况下,是不能管理数据库的。但是,他们知道应用用户的密码,如能登陆HR用户,看到HR用户下的数据。但是,每个用户也是分割的,如HR用户可以看到HR下面的数据,但是不能看到finance用户下的数据。
审计用户/管理员:这个用户可以配置database vault策略,也拥有一些alter user之类的特权命令的执行权,他们还可以查看管理dba与开发dba的一些违规操作。但是,最主要的是,他们要指定好策略,实现上面所说的,更好的控制何人、何时、何地可以访问应用程序。如,可以规定,这个数据库的某个用户数据,只能在特定的IP地址的机器上能访问;也可以规定,比如财务数据,只能从早上8点到晚上18点能接受访问,其它时间任何人都不能访问到该数据。
Oracle Database Vault是甲骨文公司安全产品系列的一个组成部分,可与Oracle标记安全(OracleLabel Security)、Oracle透明数据加密(Oracle Transparent Data Encryption)、Oracle虚拟专有数据库(Oracle Virtual Private Database)、Oracle安全备份(Oracle Secure Backup)等其他Oracle数据库安全产品一起使用,以实现更高级别的信息保护。
现在database vault遭遇到的最大的困难可能还是可靠度方面以及性能方面的问题,到底有多少人用到了这个东西,是否有bug,性能影响到底有多大等等。在性能方面,因为它会改变select语句的行为(权限),我怀疑一个策略的改变将引发众多语句的重新编译,这个情况在高可用的OLTP环境中则是比较恐怖的。
其实,数据库的安全,也仅仅是所有安全策略中的一个小部分,如果安全做的好,我们就不再仅仅是依靠dba或者是sa的人品了。
早些年,特别是Oracle版本8与版本9,Oracle图形界面做的是比较鸡肋的,不仅仅是用起来很不爽,而且极为不方便。所以,在这些版本上,使用oracle图形界面的人是少之为少。另外,因为一定的偏见,认为不用图形界面,而敲敲字符都是高手的表现,itpub曾经也出现过这样的讨论,调查有多少人能离开图形界面而工作,而且大部分的人认为,只用字符界面,如一个sqlplus就能解决所有问题,那肯定是高手。
不可否认,使用字符界面管理数据库的难度是比图形界面要大的,很多远程系统,如远程unix/linux,一般只能通过telnet或者是ssh登陆上去,这些情况下,只能使用字符界面来处理问题,所以,能通过高难度的字符界面能解决所有问题,那的确就是高手了。而且,在实际情况中,因为图形界面包装的东西太多,如果dba真的只会只用图形界面,而现在出现了一个错误,dba可能会对该错误束手无策,因为图形界面在这里不能给他提供太多的帮助。
但是,我们需要想到,如果一个公司的数据库非常多,他们的确是不需要所有的人都很精通字符界面管理,他们也招不到这么多的高手来管理数据库,专家永远只是其中一小部分,大部分的人,如果图形界面做的好,只要通过图形界面做做简单的工作就够了。这样有最明显的好处,就是成本的下降,公司对DBA的要求可能没有以前那么高,只要知道在哪里怎么点鼠标就可以了。
所以,按照Oracle的战略思想,oracle从来就没有放弃过图形界面,而且,oracle加强了图形界面的能力,如10g采用的web方式的em,在dba可以很方便的使用图形界面;如oracle把大量的内容集成到图形界面中,在字符界面你甚至找不到这些功能的操作文档,如优化模块,如一些集成功能,如database vault,等等。
oracle 11g再次对em加强,基本上通过em已经能完成了全部的字符界面能完成的数据库管理,而且,很多字符界面不支持的操作,或者是完成起来很困难的操作,现在点点鼠标就可以完成了。甚至,连一些常见错误,现在在图形界面中,都能自动处理了。那么,按照oracle的想法,以后的数据库管理,你喜欢用也好,不喜欢用也好,都去用em吧,图形界面用的好也可以培养出高手。
Oracle还不遗余力开发了集中管理模式,如OEM grid control,通过这个模块,可以通过web很方便的集中管理几十台oralce数据库,还可以是除oracle以外的数据库,甚至主机,OS等等。再想想其它公司的很多产品,如emc ecc,veritas I3,quest Central等等,都是在做基本同样的事情,看这个样子就知道,这里面的市场其实还是很大的,也证明了需求也还是瞒大的。