Chinaunix首页 | 论坛 | 博客
  • 博客访问: 143972
  • 博文数量: 161
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: -30
  • 用 户 组: 普通用户
  • 注册时间: 2017-09-21 21:45
文章分类
文章存档

2009年(1)

2008年(74)

2007年(48)

2006年(38)

我的朋友

分类: Oracle

2008-07-30 15:46:56

第 20 周
其它最佳特性

自动统计信息收集、可保证的还原数据保留以及更容易和更安全的加密方法都是 DBA 一直希望获得的一些其他特性,而现在 Oracle 数据库 10g 中拥有这些特性

哇!充满惊喜的 Oracle 数据库 10g 为 DBA 提供的最重要新特性的探索旅程已经来到最后一周。在过去 19 篇文章中,我尝试讨论可满足下一基本要求的所有工具、技巧和技术:使我们的工作更容易和更令人满意。

但如果某个特性虽极具吸引力但对 DBA 却没有很大的帮助,则在本请单中将不列出该特性。虽然如此,20 篇文章并不足以探讨 Oracle 10g 提供的所有特性 — 可能我需要写一百多篇文章才够。因此,在这篇本系列的倒数第二篇文章中,我将对 Oracle 10g 的其余新特性中应该提及的几个特性进行说明。

您的统计信息是否陈旧?不要再等待了

大部分都道,Oracle 10g 版本最后不再支持(而不是反对)基于规则的优化器 (RBO)。考虑到这种期待已久的发展即将发生,很多 Oracle9i 数据库商店升级到基于开销的优化器 (CBO),以便进入支持循环并利用查询重写和分区修剪等高级特性。但是,问题在于统计信息 — 或者说在于缺少统计信息。

因为 CBO 依靠准确的(或者说比较准确的)统计信息来产生优化的执行路径,所以 DBA 需要确保定期收集统计信息,创建另一个执行核对清单。在 10g 之前,这一过程可能由于多种原因而徒劳无功。这种困难导致产生了一种理论,即 CBO 具有“自己的思想” — 这意味着会有随意更改执行路径的行为!

在 10g 中已经消除了很多这类的顾虑,它能够自动收集统计信息。在 Oracle9i 中,您可以通过打开表监视选项 (ALTER TABLE ...MONITORING) 然后检查这些表的视图 DBA_TAB_MODIFICATIONS,检查表中的数据是否已明显更改过。

在 10g 中,已不再使用 MONITORING 语句了。而通过设置初始化参数 STATISTIC_LEVELTYPICALALL,就可以自动收集统计信息。(默认值为 TYPICAL,因此可以随即启用自动收集统计信息的功能。)Oracle 数据库 10g 具有一个预定义的调度程序(您在中已经学习过调度程序)作业,名称为 GATHER_STATS_JOB,它由 STATISTIC_LEVEL 参数的适当数值所激活。

统计信息的收集是资源相当密集的工作,因此您可能希望确保它不影响数据库的正常操作。在 10g 中,您可以使这一工作自动完成:可对一个名为 AUTO_TASK_CONSUMER_GROUP 的特定资源用户组进行预定义,用于自动执行一些任务,比如收集统计信息。该用户组确保这些统计信息收集作业的优先权低于默认用户组,因此减少或消除了自动化任务占用整个机器的风险。

如果希望将参数 STATISTIC_LEVEL 设为 TYPICAL 却不希望自动收集统计信息时该怎么办?很简单。只需使用以下语句来禁用调度程序作业即可:
BEGIN
DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');
END;

那么您为什么要这样做呢?有很多原因 — 其中一个原因是,虽然表中大部分行发生了变化,但分布情况可能没有改变,这在数据仓库中很常见。在这种情况下,您不希望再次收集统计信息,而只是希望重用原来的统计信息。另一个原因可能是您正在使用分区交换功能来刷新物化视图 (MV),并且不希望收集关于物化视图的统计信息,因为关于被交换表的统计信息也会被导入。但是,您也可以将特定的表排除在自动统计信息收集作业之外,而不需要禁止整个作业。

统计信息历史

在优化器收集统计信息时可能出现的复杂情况之一是执行计划的改变 — 也就是说,原来的优化方法在收集统计信息之前一直工作良好,但是在此之后,由于新收集的统计信息产生了不良计划,导致查询突然出错。这种问题并不少见。

为避免这种灾难,统计信息的收集作业在收集新信息之前保存当前的统计信息。如果出现问题,您总可以返回到原有的统计信息,或者至少可以检查二者之间的不同之处,以便于解决问题。

例如,假设在 5 月 31 日晚上 10:00 开始运行表 REVENUE 上的统计信息收集作业,而随后查询的性能变差。Oracle 保存了原有的统计信息,您可以通过执行以下命令重新获取这些信息:
begin
dbms_stats.restore_table_stats (
'ARUP',
'REVENUE',
'31-MAY-04 10.00.00.000000000 PM -04:00');
end;
此命令恢复到 5 月 31 日晚上 10:00 为止的统计信息,时间信息是以 TIMESTAMP 数据类型提供。这样您就立即还原了由新的统计信息收集程序所作的更改。

您能够恢复的时间长度是由保留参数所决定的。要查看当前的保留参数,可使用以下查询:
SQL> select DBMS_STATS.GET_STATS_HISTORY_RETENTION from dual;

GET_STATS_HISTORY_RETENTION
---------------------------
                         31
在本示例中表示可以保存相当于 31 天的统计信息,但并不能予以保证。要了解统计信息所覆盖到的确切时间和日期,只需使用以下查询:
SQL> select DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY from dual;

GET_STATS_HISTORY_AVAILABILITY
---------------------------------------------------------------------
17-MAY-04 03.21.33.594053000 PM -04:00
该查询表明可用的最陈旧统计信息日期为 5 月 17 日凌晨 3:21。

您可以通过执行内建的函数将保留时间设为不同的值。例如,要将其设为 45 天,可使用:
execute DBMS_STATS.ALTER_STATS_HISTORY_RETENTION (45)
有保证的还原保留功能

自动还原保留功能是在 Oracle9i 中推出的,它极其有助于减少令人讨厌的 ORA-1555 "Snapshot Too Old" 错误的出现机率。但是这些错误还是会出现,虽然其数量已大大减少。这是为什么呢?

要回答这个问题,您需要了解还原段是如何工作的。当 Oracle 内部的数据发生变化时,高速缓存中的块(在 SGA 中)立即发生变化,而过去的映像被存储在还原段中。当事务提交时,不再需要旧的映像,因此可以重用它们。如果还原段中的所有空间都被活动的事务所使用,则 Oracle 将尝试重用段中最陈旧的范围(这一进程称为“折返”,如 V$ROLLSTAT 视图中的 WRAPS 列所示)。但是,在某些情况下,特别是在长时间运行的事务中,段将会扩展,为活动的事务提供空间,如 V$ROLLSTAT 中的列 EXTENDS 所示。如果查询需要使用还原段范围中的数据来创建数据的一致性视图,但是该范围已经被重用,则查询产生 ORA-1555 错误。

初始化参数 UNDO_RETENTION_PERIOD 指定必须保留多少还原数据(以秒为单位)。通过指定时间,Oracle 确保不重用陈旧的还原范围,即使这些范围处于不活动的状态,或它们在还原保留时间内已经被更改,Oracle 也不会重用它们。这种方法减少了不活动范围以后可能被查询所意外重用的机率,这种重用会导致产生 ORA-1555 错误。

但是,虽然 UNDO_RETENTION_PERIOD 指定了可以保留多少还原数据,它并不保证得到这种结果。当段不能扩展范围时,最陈旧的不活动范围被重用,以满足当前事务的需要。因此,当查询这些范围时,某些与更改事务无关的长时运行的查询可能会失败,并产生 ORA-1555 错误。

这个问题在 10g 中得到了解决:当您创建还原表空间时,您现在可以指定对还原保留功能的“保证”。下面是一个例子:
CREATE UNDO TABLESPACE UNDO_TS1
DATAFILE '/u01/oradata/proddb01/undo_ts1_01.dbf'
SIZE 1024M
RETENTION GUARANTEE;
请注意最后的子句,它使还原表空间保证了对未过期还原范围的保留。通过对现有还原表空间进行 ALTER 操作,也可以使其作出保证,如下所示:
ALTER TABLESPACE UNDO_TS2 RETENTION GUARANTEE;
如果您不希望对保留作出保证(Oracle9i 中的行为)该怎么办?那么,可执行以下操作:
ALTER TABLESPACE UNDO_TS2 RETENTION NOGUARANTEE;
您可以使用以下语句来验证表空间是否已经保证了还原保留功能:
SELECT RETENTION
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'UNDO_TS1';
端到端跟踪

诊断性能问题的一种常见方法是启用 sql_trace 来跟踪数据库调用,然后使用 tkprof 等工具来分析输出。但是,这种方法在具有共享服务器体系结构的数据库中具有严重的局限性。在这种配置中,创建了若干个共享服务器进程,为用户的请求提供服务。当用户 BILL 连接数据库时,调度程序将连接传递到一个可用的共享服务器进程。如果没有可用的共享服务器进程,则创建一个新进程。如果开始跟踪该会话,则会跟踪由共享服务器进程所进行的调用。

现在假设 BILL 的会话变为空闲状态,而 LORA 的会话变为活动状态。此时最初为 BILL 提供服务的共享服务器被分配给 LORA 的会话。这样,发出的跟踪信息不是来自 BILL 的会话,而是来自 LORA 的会话。当 LORA 的会话变为非活动状态时,该共享服务器可以被分配给另外的活动会话,这个会话将具有完全不同的信息。

在 10g 中,通过使用端到端跟踪,已经有效地解决了这一问题。在这种情况下,跟踪不仅根据会话进行,还可根据客户标识符等可识别的名称来进行。一个名为 DBMS_MONITOR 的新程序包可用于此目的。

例如,您可能希望跟踪所有具有标识符 account_update 的会话。为建立跟踪,您可以执行:
exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('account_update');
此命令开始跟踪所有具有标识符 account_update 的会话。当 BILL 连接数据库时,他可以使用以下语句来设置客户标识符:
exec DBMS_SESSION.SET_IDENTIFIER ('account_update')
跟踪对于具有标识符 account_update 的会话起作用,因此以上的会话将会被跟踪,并会在用户卸出目标目录中产生一个跟踪文件。如果另一个用户连接数据库并将其客户标识符设置为 account_update,则自动跟踪该会话,不需要在代码中设置任何其他的命令。直到使用以下命令禁用跟踪功能前,将跟踪所有具有客户标识符 account_update 的会话:
exec DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE('account_update');
作为结果的跟踪文件可以由 tkprof 进行分析。但是,每个会话都产生不同的跟踪文件。为了正确地诊断故障,我们关心合并的跟踪文件而不是单独的跟踪文件。我们如何获得合并的跟踪文件呢?

很简单。利用一种称为 trcsess 的工具,您可以将那些与客户标识符 account_update 相关的信息提取到一个单独的文件中,通过 tkprof 可以处理该文件。在以上的案例中,您可以转到用户卸出目标目录中并运行:
trcsess output=account_update_trc.txt clientid=account_update *
此命令创建一个名为 account_update_trc.txt 的文件,该文件与常规的跟踪文件类似,但它只包含与那些具有客户标识符 account_update 的会话相关的信息。该文件可以使用 tkprof 进行处理,以获得经过分析的输出。

将这种方法和前一种更困难的跟踪信息收集方法对比此外,跟踪是由客户标识符这样的变量来启用和禁止的,而不需要从该会话中调用 alter session set sql_trace = true。同一程序包中的另一个过程 SERV_MOD_ACT_TRACE_ENABLE 能够在其他组合方式中启用跟踪功能,如用于特定服务、模块或操作的组合,可以利用 dbms_application_info package 来进行设置。

数据库的使用

您的 Oracle 销售代表将会确认,分区功能是要额外购买的选件,而在如今这个控制成本的时代,您可能希望了解用户是否使用该选件 — 如果使用,使用的频率怎样。

不必依赖于用户的回答,只需查询数据库即可。自动工作负载信息库(在中有介绍)收集所有已安装特性的使用情况信息,尽管每周只收集一次。

两个非常重要的视图显示了数据库的使用模式。其中之一是 DBA_HIGH_WATER_MARK_STATISTICS,它显示当前数据库中使用的每个特性的最大值。以下是一个示例输出。
NAME             HIGHWATER LAST_VALUE DESCRIPTION
--------------- ---------- ---------- ----------------------------------------------------------
USER_TABLES            401        401 Number of User Tables
SEGMENT_SIZE    1237319680 1237319680 Size of Largest Segment (Bytes)
PART_TABLES             12          0 Maximum Number of Partitions belonging to an User Table
PART_INDEXES            12          0 Maximum Number of Partitions belonging to an User Index
USER_INDEXES           832        832 Number of User Indexes
SESSIONS                19         17 Maximum Number of Concurrent Sessions seen in the database
DB_SIZE         7940079616 7940079616 Maximum Size of the Database (Bytes)
DATAFILES                6          6 Maximum Number of Datafiles
TABLESPACES              7          7 Maximum Number of Tablespaces
CPU_COUNT                4          4 Maximum Number of CPUs
QUERY_LENGTH          1176       1176 Maximum Query Length
可以看到,此视图显示了一些有关数据库使用情况的有价值的信息 — 如用户创建了一个最多可拥有 12 个分区的表,但现在却没有使用一个分区 (LAST_VALUE = 0)。这些信息在关闭状态下也持续存在,这对于计划操作非常有用,比如移植到不同的主机。

但是,上述视图仍然没有回答我们所有的问题。它只是告诉我们曾经创建了具有 12 个分区的表,但没有说明该特性的最后一次使用时间。另一个视图 DBA_FEATURE_USAGE_STATISTICS 显示了数据库各种特性的使用情况,它可以回答这个问题。以下是该视图分区特性的显示情况,其中的列以纵向格式显示。
DBID                          : 4133493568
NAME                          :Partitioning
VERSION                       : 10.1.0.1.0
DETECTED_USAGES               : 12
TOTAL_SAMPLES                 : 12
CURRENTLY_USED                :FALSE
FIRST_USAGE_DATE              :16-oct-2003 13:27:10
LAST_USAGE_DATE               :16-dec-2003 21:20:58
AUX_COUNT                     :
FEATURE_INFO                  :
LAST_SAMPLE_DATE              :23-dec-2003 21:20:58
LAST_SAMPLE_PERIOD            : 615836
SAMPLE_INTERVAL               : 604800
DESCRIPTION                   :Oracle Partitioning option is being used -
there is at least one partitioned object created.
如本视图所示,现在数据库中没有使用分区特性(列 CURRENTLY_USED 的值为 FALSE),最后一次使用该特性的时间是 2003 年 12 月 16 日晚上 9:20。使用信息的采样时间为 604,800 秒或者说是 7 天,示于列 SAMPLE_INTERVAL 中。列 LAST_SAMPLE_DATE 显示了对该使用信息的最后采样时间,表明此信息的新旧程度。

除了命令行接口之外,企业管理器 10g 还显示以下信息。在 EM 中,在 Administration 标签处单击 Configuration Management 下方的“Database Usage Statistics”链接。(参见图 1 和图 2。)

图 1
图 1:数据库使用情况的统计信息页面

图 2
图 2:数据库使用情况的统计信息;下钻特性

更容易和更安全的加密

还记得程序包 DBMS_OBFUSCATION_TOOLKIT (DOTK) 吗?它是 Oracle9i 以及更低版本的数据库中唯一可用的加密方法。尽管该程序包对于大部分数据库而言已经足够了,但是象大多数安全产品一样,它很快就无法应付那些涉及高度敏感信息的高超的黑客攻击。在所缺少的功能中,一个值得注意的功能是对高级加密标准 (AES) 的支持,该标准是以前的数字加密标准 (DES) 以及三倍 DES (DES3) 的一个功能更强的后继标准。

在 10g 中,一种更加完善的加密方法 DBMS_CRYPTO 用于处理这种问题。这个内建的程序包提供了 DOTK 中缺少的所有功能,并且对现有的函数和过程进行了增强。例如,DBMS_CRYPTO 可以使用新的 256 位 AES 算法进行加密。函数 ENCRYPT(也将其作为过程而超载)接受以下的几个参数:

参数 说明
SRC 要加密的输入。它必须是 RAW 数据类型;任何其他数据类型都必须进行转换。例如,字符变量 l_inp 的转换方法是:
utl_i18n.string_to_raw (p_in_val, 'AL32UTF8');
因为必须将字符串转换为 RAW 和字符集 AL32UTF8,所以使用了一个称为 UTL_IL8N 的新程序包。与 DOTK 不同,DBMS_CRYPTO 不接受将字符变量作为参数。要注意的另一点是,您不必像在 DOTK 程序包中一样,将字符长度填充为 16 的倍数。函数(或过程)自动将其补齐。
KEY 在此处指定密钥。密钥基于所使用的算法,必须具有适当的长度。
TYP 此参数指定所使用的加密和填充类型。例如,如果您希望使用 AES 256 位算法、密码分组链接和 PKCS#5 填充方法,则可以使用内建的常数,如下所示:
typ => dbms_cryptio.encrypt_aes256 + 
dbms_cryptio.chain_cbc + 
	   dbms_cryptio.pad_pkcs5

ENCRYPT 函数返回 RAW 类型的加密值,可使用以下方法将该值转换为字符串
utl_i18n.raw_to_char (l_enc_val, 'AL32UTF8')
这与转换为 RAW 的过程相反。

加密的相反操作是解密,此操作由函数 DECRYPT 提供(并将其作为过程而超载),该函数接受类似的参数。使用这个新的程序包,您可以在数据库应用程序的内部构建完善的安全模型。

结论

我先前曾提到,讨论 Oracle 数据库 10g 中所有与 DBA 相关的新特性是不可能的,但是我尝试在这 20 周中选择性地讨论一些特性,在本周专门讨论了在前面 19 篇文章中无法涉及到一些重要但杂样的内容。我希望本系列为您提供了一些信息,并对您有所帮助。再一次请您尽情提出意见,并且不要忘记写信告诉我您最喜欢哪个特性。
阅读(1246) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~