您的位置:首页 > 博客中心 > 数据库 >

【转载】Oracle ACE总监对Oracle 12c的一些新特性总结

时间:2022-03-13 23:23

本文是Oracle ACE总监Syed Jaffer Hussain对Oracle数据库12c的一些新特性总结,包括数据库管理、RMAN、高可用性以及性能调优等内容。

主要内容:
1. 在线迁移活跃的数据文件
2. 表分区或子分区的在线迁移
3. 不可见字段
4. 相同字段上的多重索引
5. DDL日志
6. 临时undo
7. 新的备份用户特权
8. 如何在RMAN中执行SQL语句
9. RMAN中的表级别恢复
10. PGA的大小限制问题
11. 对表分区维护的增强
12. 数据库升级的改进
13. 通过网络恢复数据文件
14. 对Data Pump的增强
15. 实时自动数据诊断监视器(ADDM)
16. 并发统计信息收集

1. 在线重命名和重新定位活跃数据文件

不 同于以往的版本,在Oracle数据库12c R1版本中对数据文件的迁移或重命名不再需要太多繁琐的步骤,即把表空间置为只读模式,接下来是对数据文件进行离线操作。在12c R1中,可以使用ALTER DATABASE MOVE DATAFILE这样的SQL语句对数据文件进行在线重命名和移动。而当此数据文件正在传输时,终端用户可以执行查询,DML以及DDL方面的任务。另 外,数据文件可以在存储设备间迁移,如从非ASM迁移至ASM,反之亦然。

重命名数据文件:

1 SQL> ALTER DATABASE MOVE DATAFILE ‘/u00/data/users01.dbf‘ TO ‘/u00/data/users_01.dbf‘;

从非ASM迁移数据文件至ASM:

1 SQL> ALTER DATABASE MOVE DATAFILE ‘/u00/data/users_01.dbf‘ TO ‘+DG_DATA‘;

将数据文件从一个ASM磁盘群组迁移至另一个ASM磁盘群组:

1 SQL> ALTER DATABASE MOVE DATAFILE ‘+DG_DATA/DBNAME/DATAFILE/users_01.dbf ‘ TO ‘+DG_DATA_02‘;

在数据文件已存在于新路径的情况下,以相同的命名将其覆盖:

1 SQL> ALTER DATABASE MOVE DATAFILE ‘/u00/data/users_01.dbf‘ TO ‘/u00/data_new/users_01.dbf‘ REUSE;

复制文件到一个新路径,同时在原路径下保留其拷贝

1 SQL> ALTER DATABASE MOVE DATAFILE ‘/u00/data/users_01.dbf‘ TO ‘/u00/data_new/users_01.dbf‘ KEEP;

当通过查询v$session_longops动态视图来移动文件时,你可以监控这一过程。另外,你也可以引用alert.log,Oracle会在其中记录具体的行为。

2. 表分区或子分区的在线迁移

在Oracle 12c R1中迁移表分区或子分区到不同的表空间不再需要复杂的过程。与之前版本中未分区表进行在线迁移类似,表分区或子分区可以在线或是离线迁移至一个不同的表 空间。当指定了ONLINE语句,所有的DML操作可以在没有任何中断的情况下,在参与这一过程的分区或子分区上执行。与此相反,分区或子分区迁移如果是 在离线情况下进行的,DML操作是不被允许的。

示例:

1 SQL> ALTER TABLE table_name MOVE PARTITION|SUBPARTITION partition_name TO tablespace tablespace_name;
2 SQL> ALTER TABLE table_name MOVE PARTITION|SUBPARTITION partition_name TO tablespace tablespace_name UPDATE INDEXES ONLINE;

第一个示例是用来在离线状况下将一个表分区或子分区迁移至一个新的表空间。第二个示例是在线迁移表分区或子分区并维护表上任何本地或全局的索引。此外,当使用ONLINE语句时,DML操作是不会中断的。

重要提示::

UPDATE INDEXES语句可以避免出现表中任何本地或全局索引无法使用的情况。
表的在线迁移限制也适用于此。
引入加锁机制来完成这一过程,当然它也会导致性能下降并会产生大量的redo,这取于分区和子分区的大小。

3. 不可见字段

在Oracle 11g R1中,Oracle以不可见索引和虚拟字段的形式引入了一些不错的增强特性。继承前者并发扬光大,Oracle 12c R1中引入了不可见字段思想。在之前的版本中,为了隐藏重要的数据字段以避免在通用查询中显示,我们往往会创建一个视图来隐藏所需信息或应用某些安全条 件。

在12c R1中,你可以在表中创建不可见字段。当一个字段定义为不可见时,这一字段就不会出现在通用查询中,除非在SQL语句或条件中有显式的提及这一字段,或是在表定义中有DESCRIBED。要添加或是修改一个不可见字段是非常容易的,反之亦然。

1 SQL> CREATE TABLE emp (eno number(6), ename name varchar2(40), sal number(9) INVISIBLE);
2 SQL> ALTER TABLE emp MODIFY (sal visible);

你必须在INSERT语句中显式提及不可见字段名以将不可见字段插入到数据库中。虚拟字段和分区字段同样也可以定义为不可见类型。但临时表,外部表和集群表并不支持不可见字段。


4. 相同字段上的多重索引

在Oracle 12c R1之前,一个字段是无法以任何形式拥有多个索引的。或许有人会想知道为什么通常一个字段需要有多重索引,事实上需要多重索引的字段或字段集合是很多的。 在12c R1中,只要索引类型的形式不同,一个字段就可以包含在一个B-tree索引中,同样也可以包含在Bitmap索引中。注意,只有一种类型的索引是在给定 时间可用的。


5. DDL日志

在 之前的版本中没有可选方法来对DDL操作进行日志记录。而在12c R1中,你现在可以将DDL操作写入xml和日志文件中。这对于了解谁在什么时间执行了create或drop命令是十分有用的。要开启这一功能必须对 ENABLE_DDL_LOGGING 初始参数加以配置。这一参数可以在数据库或会话级加以设置。当此参数为启用状态,所有的DDL命令会记录在$ORACLE_BASE/diag /rdbms/DBNAME/log|ddl 路径下的xml和日志文件中。一个xml中包含DDL命令,IP地址,时间戳等信息。这可以帮助确定在什么时候对用户或表进行了删除亦或是一条DDL语句 在何时触发。

开启DDL日志功能

1 SQL> ALTER SYSTEM|SESSION SET ENABLE_DDL_LOGGING=TRUE;

以下的DDL语句可能会记录在xml或日志文件中:

1 CREATE|ALTER|DROP|TRUNCATE TABLE
2 DROP USER
3 CREATE|ALTER|DROP PACKAGE|FUNCTION|VIEW|SYNONYM|SEQUENCE


6. 临时undo

每 个Oracle数据库包含一组与系统相关的表空间,例如SYSTEM,SYSAUX,UNDO & TEMP,并且它们在Oracle数据库中每个都用于不同的目的。在Oracle 12c R1之前,undo记录是由临时表产生并存储在undo表空间中的,这更类似于一个通用或持久的表撤销记录。然而,由于在12c R1中引入了临时undo功能,那些临时undo记录现在就可以存储在临时表中,而不是存储在undo表空间中。临时undo的主要好处在于:由于信息不 会写入undo日志,undo表空间的开销得以减少并且产生的undo数据会更少。而对于在会话级还是数据库级开启临时undo功能你是可以灵活选择的。

启用临时undo功能

要使用这一新功能,需要做以下设置:

兼容性参数必须设置为12.0.0或更高
启用 TEMP_UNDO_ENABLED 初始化参数
由于临时undo记录现在是存储在一个临时表空间中的,你需要有足够的空间来创建这一临时表空间
对于会话级,你可以使用:ALTER SYSTEM SET TEMP_UNDO_ENABLE=TRUE;
查询临时undo信息

以下所列的字典视图是用来查看或查询临时undo数据相关统计信息的:

1 V$TEMPUNDOSTAT
2 DBA_HIST_UNDOSTAT
3 V$UNDOSTAT

要禁用此功能,你只需做以下设置:

1 SQL> ALTER SYSTEM|SESSION SET TEMP_UNDO_ENABLED=FALSE;


7. 备份特定用户特权

在11g R2中,引入了SYSASM特权来执行ASM的特定操作。同样地,在12c中引入了SYSBACKUP特权用来在 RMAN中执行备份和恢复命令。因此,你可以在数据库中创建一个本地用户并在不授予其SYSDBA权限的情况下,通过授予SYSBACKUP权限让其能够 在RMAN中执行备份和恢复相关的任务。

1 $ ./rman target "username/password as SYSBACKUP"


8. 如何在RMAN中执行SQL语句

在12c中,你可以在不需要SQL前缀的情况下在RMAN中执行任何SQL和PL/SQL命令,即你可以从RMAN直接执行任何SQL和PL/SQL命令。如下便是在RMAN中执行SQL语句的示例

1 RMAN> SELECT username,machine FROM v$session;
2 RMAN> ALTER TABLESPACE users ADD DATAFILE SIZE 121m;


9. RMAN中的表恢复和分区恢复

Oracle 数据库备份主要分为两类:逻辑和物理备份。每种备份类型都有其自身的优缺点。在之前的版本中,利用现有物理备份来恢复表或分区是不可行的。为了恢复特定对 象,逻辑备份是必需的。对于12c R1,你可以在发生drop或truncate的情况下从RMAN备份将一个特定的表或分区恢复到某个时间点或SCN。

当通过RMAN发起一个表或分区恢复时,大概流程是这样的:

确定要恢复表或分区所需的备份集
在恢复表或分区的过程中,一个辅助数据库会临时设置为某个时间点利用数据泵将所需表或分区导出到一个dumpfile
你可以从源数据库导入表或分区(可选)
在恢复过程中进行重命名操作
以下是一个通过RMAN对表进行时间点恢复的示例(确保你已经对稍早的数据库进行了完整备份):

1 RMAN> connect target "username/password as SYSBACKUP";
2 RMAN> RECOVER TABLE username.tablename UNTIL TIME ‘TIMESTAMP…‘
3 AUXILIARY DESTINATION ‘/u01/tablerecovery‘
4 DATAPUMP DESTINATION ‘/u01/dpump‘
5 DUMP FILE ‘tablename.dmp‘
6 NOTABLEIMPORT -- this option avoids importing the table automatically.(此选项避免自动导入表)
7 REMAP TABLE ‘username.tablename‘: ‘username.new_table_name‘; -- can rename table with this option.(此选项可以对表重命名)

重要提示:

确保对于辅助数据库在/u01文件系统下有足够的可用空间,同时对数据泵文件也有同样保证
必须要存在一份完整的数据库备份,或者至少是要有SYSTEM相关的表空间备份
以下是在RMAN中应用表或分区恢复的限制和约束:

SYS用户表或分区无法恢复
存储于SYSAUX和SYSTEM表空间下的表和分区无法恢复
当REMAP选项用来恢复的表包含NOT NULL约束时,恢复此表是不可行的

10. 限制PGA的大小

在Oracle 12c R1之前,没有选项可以用来限制和控制PGA的大小。虽然你设置某个大小为PGA_AGGREGATE_TARGET 的初始参数,Oracle会根据工作负载和需求来动态地增大或减小PGA的大小。而在12c中,你可以通过开启自动PGA管理来对PGA设定硬性限制,这 需要对PGA_AGGREGATE_LIMIT 参数进行设置。因此,你现在可以通过设置新的参数来对PGA设定硬性限制以避免过度使用PGA。

1 SQL> ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=2G;
2 SQL> ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=0; --disables the hard limit

重要提示::

当超过了当前PGA的限制,Oracle会自动终止/中止会话或进程以保持最合适的PGA内存。

11. 对表分区维护的增强

我解释了如何在线或是离线状态下迁移一个表分区或子分区到另一个不同的表空间。在本文中,主要介绍表分区其他方面的改进。

添加多个新分区

在Oracle 12c R1之前,一次只可能添加一个新分区到一个已存在的分区表。要添加一个以上的新分区,需要对每个新分区都单独执行一次ALTER TABLE ADD PARTITION语句。而Oracle 12c只需要使用一条单独的ALTER TABLE ADD PARTITION 命令就可以添加多个新分区,这增加了数据库灵活性。以下示例说明了如何添加多个新分区到已存在的分区表:

1 SQL> CREATE TABLE emp_part
2 (eno number(8), ename varchar2(40), sal number (6))
3 PARTITION BY RANGE (sal)
4 (PARTITION p1 VALUES LESS THAN (10000),
5 PARTITION p2 VALUES LESS THAN (20000),
6 PARTITION p3 VALUES LESS THAN (30000)
7 );

添加两个新分区:

1 SQL> ALTER TABLE emp_part ADD PARTITION
2 PARTITION p4 VALUES LESS THAN (35000),
3 PARTITION p5 VALUES LESS THAN (40000);

同样,只要MAXVALUE分区不存在,你就可以添加多个新分区到一个列表和系统分区表。

如何删除和截断多个分区/子分区

作 为数据维护的一部分,DBA通常会在一个分区表上进行删除或截断分区的维护任务。在12c R1之前,对于一个已存在的分区表一次只可能删除或截断一个分区。而对于Oracle 12c, 可以用单条ALTER TABLE table_name {DROP|TRUNCATE} PARTITIONS命令来撤销或合并多个分区和子分区。

下例说明了如何在一个已存在分区表上删除或截断多个分区:

1 SQL> ALTER TABLE emp_part DROP PARTITIONS p4,p5;
2 SQL> ALTER TABLE emp_part TRUNCATE PARTITONS p4,p5;

要保持索引更新,使用UPDATE INDEXES或UPDATE GLOBAL INDEXES语句,如下所示:

1 SQL> ALTER TABLE emp_part DROP PARTITIONS p4,p5 UPDATE GLOBAL INDEXES;
2 SQL> ALTER TABLE emp_part TRUNCATE PARTITIONS p4,p5 UPDATE GLOBAL INDEXES;

如果你在不使用UPDATE GLOBAL INDEXES 语句的情况下删除或截断一个分区,你可以在USER_INDEXES或USER_IND_PARTITIONS 字典视图下查询ORPHANED_ENTRIES 字段以找出是否有索引包含任何的过期条目。

将单个分区分割为多个新分区

在12c中新增强的SPLIT PARTITION 语句可以让你只使用一个单独命令将一个特定分区或子分区分割为多个新分区。下例说明了如何将一个分区分割为多个新分区:

01 SQL> CREATE TABLE emp_part
02 (eno number(8), ename varchar2(40), sal number (6))
03 PARTITION BY RANGE (sal)
04 (PARTITION p1 VALUES LESS THAN (10000),
05 PARTITION p2 VALUES LESS THAN (20000),
06 PARTITION p_max (MAXVALUE)
07 );
08 SQL> ALTER TABLE emp_part SPLIT PARTITION p_max INTO
09 (PARTITION p3 VALUES LESS THAN (25000),
10 PARTITION p4 VALUES LESS THAN (30000), PARTITION p_max);

将多个分区合并为一个分区

你可以使用单条ALTER TBALE MERGE PARTITIONS 语句将多个分区合并为一个单独分区:

01 SQL> CREATE TABLE emp_part
02 (eno number(8), ename varchar2(40), sal number (6))
03 PARTITION BY RANGE (sal)
04 (PARTITION p1 VALUES LESS THAN (10000),
05 PARTITION p2 VALUES LESS THAN (20000),
06 PARTITION p3 VALUES LESS THAN (30000),
07 PARTITION p4 VALUES LESS THAN (40000),
08 PARTITION p5 VALUES LESS THAN (50000),
09 PARTITION p_max (MAXVALUE)
10 );
11 SQL> ALTER TABLE emp_part MERGE PARTITIONS p3,p4,p5 INTO PARTITION p_merge;

如果分区范围形成序列,你可以使用如下示例:

1 SQL> ALTER TABLE emp_part MERGE PARTITIONS p3 TO p5 INTO PARTITION p_merge;


12. 数据库升级改进

每当一个新的Oracle版本发布,DBA所要面临的挑战就是升级过程。该部分我将介绍12c中引入的针对升级的两个改进。

预升级脚本

在12c R1中,原有的utlu[121]s.sql 脚本由一个大为改善的预升级信息脚本preupgrd.sql所取代。除了预升级检查验证,此脚本还能以修复脚本的形式解决在升级过程前后出现的各种问题。

可 以对产生的修复脚本加以执行来解决不同级别的问题,例如,预升级和升级后的问题。当手动升级数据库时,脚本必须在实际升级过程初始化之前加以手动执行。然 而,当使用DBUA工具来进行数据库升级时,它会将预升级脚本作为升级过程的一部分加以自动执行,而且会提示你去执行修复脚本以防止报错。

如何执行脚本:

1 SQL> @$ORACLE_12GHOME/rdbms/admin/preupgrd.sql

以上脚本会产生一份日志文件以及一个[pre/post]upgrade_fixup.sql 脚本。所有这些文件都位于$ORACLE_BASE/cfgtoollogs 目录下。在你继续真正的升级过程之前,你应该浏览日志文件中所提到的建议并执行脚本以修复问题。

注意:你要确保将preupgrd.sql和utluppkg.sql 脚本从12c Oracle的目录home/rdbms/admin directory拷贝至当前的Oracle的database/rdbms/admin路径。

并行升级功能

数据库升级时间的长短取决于数据库上所配置的组件数量,而不是数据库的大小。在之前的版本中,我们是无法并行运行升级程序,从而快速完成整个升级过程的。

在12c R1中,原有的catupgrd.sql 脚本由catctl.pl 脚本(并行升级功能)替代,现在我们可以采用并行模式运行升级程序了。

以下流程说明了如何初始化并行升级功能(3个过程);你需要在升级模式下在启动数据库后运行这一脚本

1 cd $ORACLE_12_HOME/perl/bin
2 $ ./perl catctl.pl –n 3 -catupgrd.sql

以上两个步骤需要在手动升级数据库时运行。而DBUA也继承了这两个新变化。


13. 通过网络恢复数据文件

在12c R1中另一个重要的增强是,你现在可以在主数据库和备用数据库之间用一个服务名重新获得或恢复数据文件、控制文件、参数文件、表空间或整个数据库。这对于同步主数据库和备用数据库极为有用。

当 主数据库和备用数据库之间存在相当大的差异时,你不再需要复杂的前滚流程来填补它们之间的差异。RMAN能够通过网络执行备用恢复以进行增量备份,并且可 以将它们应用到物理备用数据库。你可以用服务名直接将所需数据文件从备用点拷贝至主站,这是为了防止主数据库上数据文件、表空间的丢失,或是没有真正从备 份集恢复数据文件。

以下流程演示了如何用此新功能执行一个前滚来对备用数据库和主数据库进行同步:

在物理备用数据库上:

1  ./rman target "username/password@standby_db_tns as SYSBACKUP"
2 RMAN> RECOVER DATABASE FROM SERVICE primary_db_tns USING COMpreSSED BACKUPSET;

以 上示例使用备用数据库上定义的primary_db_tns 连接字符串连接到主数据库,然后执行了一个增量备份,再将这些增量备份传输至备用目的地,接着将应用这些文件到备用数据库来进行同步。然而,需要确保已经 对primary_db_tns 进行了配置,即在备份数据库端将其指向主数据库。

在以下示例中,我将演示一个场景通过从备用数据库获取数据文件来恢复主数据库上丢失的数据文件:

在主数据库上:

1 ./rman target "username/password@primary_db_tns as SYSBACKUP"
2 RMAN> RESTORE DATAFILE ‘+DG_DISKGROUP/DBANME/DATAFILE/filename’FROM SERVICE standby_db_tns;


14. 对Data Pump的增强

Data Pump版本有了不少有用的改进,例如在导出时将视图转换为表,以及在导入时关闭日志记录等。

关闭redo日志的生成

Data Pump中引入了新的TRANSFORM选项,这对于对象在导入期间提供了关闭重做生成的灵活性。当为TRANSFORM选项指定了 DISABLE_ARCHIVE_LOGGING 值,那么在整个导入期间,重做生成就会处于关闭状态。这一功能在导入大型表时缓解了压力,并且减少了过度的redo产生,从而加快了导入。这一属性还可应 用到表以及索引。以下示例演示了这一功能:

1 $ ./impdp directory=dpump dumpfile=abcd.dmp logfile=abcd.log TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y

将视图转换为表

这是Data Pump中另外一个改进。有了VIEWS_AS_TABLES 选项,你就可以将视图数据载入表中。以下示例演示了如何在导出过程中将视图数据载入到表中:

1 $ ./expdp directory=dpump dumpfile=abcd.dmp logfile=abcd.log views_as_tables=my_view:my_table


15. 实时自动数据诊断监视器 (ADDM) 分析

通过使用诸如AWR、ASH以及ADDM之类的自动诊断工具来分析数据库的健康状况,是每个DBA日程工作的一部分。尽管每种工具都可以在多个层面衡量数据库的整体健康状况和性能,但没有哪个工具可以在数据库反应迟钝或是完全挂起的时候使用。

当数据库反应迟钝或是挂起状态时,而且你已经配置了Oracle 企业管理器 12c的云控制,你就可以对严重的性能问题进行诊断。这对于你了解当前数据库发生了什么状况有很大帮助,而且还能够对此问题给出解决方案。

以下步骤演示了如何在Oracle 企业管理器 12c上分析数据库状态:

在访问数据库访问主页面从Performance菜单选择Emergency Monitoring 选项。这会显示挂起分析表中排名靠前的阻止会话。
在Performance菜单选择Real-Time ADDM 选项来执行实时ADDM分析。
在收集了性能数据后,点击Findings标签以获得所有结果的交互总结。

16. 同时在多个表上收集统计数据

在 之前的Oracle数据库版本中,当你执行一个DBMS_STATS 程序来收集表、索引、模式或者数据库级别的统计数据时,Oracle习惯于一次一个表的收集统计数据。如果表很大,那么推荐你采用并行方式。在12c R1中,你现在可以同时在多个表、分区以及子分区上收集统计数据。在你开始使用它之前,你必须对数据库进行以下设置以开启此功能:

1 SQL> ALTER SYSTEM SET RESOURCE_MANAGER_PLAN=‘DEFAULT_MAIN‘;
2 SQL> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=4;
3 SQL> EXEC DBMS_STATS.SET_GLOBAL_preFS(‘CONCURRENT‘, ‘ALL‘);
4 SQL> EXEC DBMS_STATS.GATHER_SCHEMA_STATS(‘SCOTT‘);

 

发表在  | 标签为  | 

发表于  由 

1、buffer busy waits

     从本质上来讲,这个等待事件的产生仅仅说明了一个会话在等待一个Buffer(数据块),但是导致这现象的原因却是很多种,常见的两种是:

1.当一个会话试图修改一个数据块,但这个数据块正在被另一个会话修改时。

2.当一个会话需要读取一个数据块,但这个数据块正在被另一个会话读取到内从中时。

     这里需要解释一个概念,Oracle操作的最小单位是块(Block),即使你要修改一条记录,你也需要对这条记录所在的这个数据块做操作,当你对这个数据块做修改的时候,其他的会话将被阻止对这个数据块上的数据作修改(即使其他用户修改的不是当前用户修改的数据),但是可以以一致性的方式读来读取这个数据块,当前的用户修改完这个数据块后,将会立即释放掉加载这个数据块上的排他锁定,这样另一个会话就可以继续修改它,修改操作是一个非常短暂的时间,这种加锁的机制我们在前面讲过,它叫做Latch

     当一个会话修改一个数据块时,是按照以下的步骤来完成的:

a、以排他的方式获得这个数据块(Latch)

b、修改这个数据块

c、释放Latch

    buffer busy waits等待事件常见于数据库中存在热块的时候,当多个用户频繁的读取或者修改同样的数据块时,这个等待事件就会产生,如果等待的时间很长,我们在AWR或者Statpack报告中就可以看到。

1 这个等待事件包含3个参数:
2 File#--等待访问数据块所在的文件id 号。
3 Blocks---等待访问的数据块号。
4 Id ----在10g之前,这个值表示一个等待事件的原因,10g之后则表示等待事件的类别。


2、buffer latch

     内存中数据块的存放位置是记录在一个Hash列表(cachebufferchains)当中的,当一个会话需要访问某个数据块时,它首先要搜索这个Hash列表,从列表中获得数据块的地址,然后通过这个地址去访问需要的数据块,这个列表Oracle会使用一个Latch来保护它的完整性,当一个会话需要访问这个列表时,需要获取一个Latch,这有这样,才能保证这个列表在这个回话的浏览当中不会发生改变。

产生buffer latch 的等待事件的主要原因是:

   1、buffer chains太长,导致会话搜索这个列表花费的时间太长,使其它的会话处于等待状态。

   2、同样的数据块被频繁访问,就是我们通常说的热块问题。

  如果buffer chains太长时,我们可以使用多个buffer pool的方式来创建更多了buffer chains,或者使用参数DB_BLOCK_LRU_LATCHES来增加Latch的数量,以便于更多的会话可以获得Latch,这两种方法可以同时使用。

1 这个等待事件包含2个参数:
2 latchaddr---会话申请的lach 在SGA中的虚拟地址,通过以下的SQL可以根据这个
3 地址找到它对应的latch名称:
4 select *
5 from v$latch a, v$latchname b
6 where addr=latch addr
7 anda.latch#=b.latch#;
8 chain#----buffer chains hash列表中的索引值,当这个参数的值等于s0xfffffff时,说明当前的会话正在等待一个LRU latch。

 

 3、controlfile parallel write

     当数据库中有多个控制文件的拷贝时,Oracle需要保证信息同步的写到各个控制文件当中,这是一个并行的物理操作过程,因此称作控制文件并行写,当发生这样的操作时,就会产生controlfile parallel write等待事件。

控制文件频繁的写入的原因很多,比如:

a、日志切换太过频繁,导致控制文件信息相应的需要频繁的更新。

b、系统I/O出现瓶颈,导致所有的I/O出现等待。

c、当系统出现日志切换过于频繁时,可以考虑适当的增大日志的文件的大小来降低日志切

换频率。

    当系统出现大量的controlfile parallel write等待事件时,可以通过比如降低控制文件的拷贝数量,将控制文件的拷贝存放在不同的物理磁盘上的方式来缓解I/O征用。

1 这个等待事件包含三个参数:
2 Files----Oracle要写入的控制文件个数。
3 Blocks----写入控制文件的数据块数目。
4 Requests----写入控制请求的I/O次数。

 

4、controlfile sequential read

    当数据库需要读取控制文件上的信息时,会出现这个等待事件,因为控制文件的信息时顺序写的,所以读取的时候也是顺序的,因此称作控制文件顺序读,它经常发生在以下情况下:

 a、备份控制文件

 b、RAC环境下不同实例之间控制文件的信息共享。

 c、读取控制文件的文件头信息。

 d、读取控制文件其它信息。

1 这个等待事件的包含以下3个参数:
2 File#----要读取信息的控制文件的文件号。
3 Block#----读取控制文件信息的起始数据块号。
4 Blocks----需要读取的控制文件数据块数目。

 

5、db file parallel read

     这是一个容易引起误导的等待事件,实际上这个等待事件和并行操作(比如并行查询,并行DML)没有关系,这个事件发生在数据库恢复的时候,当有一些数据块需要恢复的时候,Oracle会以并行的方式把它们从数据文件中读入到内存进行恢复操作。

1 这个等待事件包含三个参数:
2 Files----操作需要读取的文件个数。
3 Blocks----操作需要读取的数据块个数。
4 Requests----操作需要执行的I/O次数。


6、db file parallel write

    这是一个后台等待事件,它同样和用户的并行操作没有关系,它是由后台进程DBWR产生的,当后台进程DBWR向磁盘上写入脏数据时,会发生这个等待。

    DBWR会批量的将脏数据并行的写入到磁盘上相应的数据文件中,在这个批次作业完成之前,DBWR将出现这个等待事件,如果仅仅是这一个等待事件,对用户的操作并没有太大的影响,当伴随着出现free buffer waits等待事件时,说明此时内存中可用的空间不足,这时候将会影响的用户的操作,比如影响的用户将数据块读入到内存中。

    当出现dbfile parallel write等待事件时,可以通过启用操作系统的异步I/O的方式来缓解这个等待,当使用异步I/O时,DBWR不再需要一直等到所有数块都全部写入到磁盘上,它只需要等到数据写入到一个百分比之后,就可以继续进行进行后续的操作。

1 这个等待事件包含2个参数:
2 Requests-----操作需要执行的I/O次数。
3 Timeouts----等待的超时时间。

 

7、db file scattered read

    这个等待事件在实际生产数据库中经常可以看到,这是一个用户操作引起的等待事件,当用户发出每次I/O需要读取多个数据块这样的SQL操作时,会产生这个等待事件,最常见的2中情况是全表扫描(FTS–FULLTABLESCAN)和索引快速扫描(IFFS–INDEX FAST FULL SCAN)。

    这个名称中的scattered(发散)可能会导致很多人认为它是以scattered的方式来读取数据块的,其实恰恰相反,当发生这种等待事件时,SQL的操作都是都是顺序地读取数据块的,比如FTS或者IFFS方式(如果忽略需要读取的数据块已经存在内存中的情况)。

   其实这里scattered指的是读取的数据块在内存中的存放方式,它们被读取到内存中后,是以分散的方式存放在内存中,而不是连续的。

1 这个等待事件包含3个参数:
2 File#----要读取的数据块所在数据文件的文件号。
3 Block#----要读取的起始数据块号。
4 Blocks----需要读取的数据块数目。

 

8、db file sequential read

    这个等待事件在实际生产数据库也非常常见,当Oracle需要每次I/O只读取单个数据块这样的操作时,会产生这个等待事件,最常见的情况有索引的访问(除IFFS以外的方式),回滚操作,以ROWID的方式访问表中的数据,重建控制文件,对文件头做DUMP等。

这里面的sequential(顺序)也并非指的是Oracle按照顺序的方式来访问数据,和db file scatteredread一样,它指的是读取的数据块在内存中是以连续的方式存放的,大家不要被误导(至少有一段时间我是被误导了的)。

1 这个等待事件包含3个参数:
2 File#----要读取的数据块所在数据文件的文件号。
3 Block#----要读取的起始数据块号。
4 Blocks----需要读取的数据块数目(在这里应该等于1)。


9、db file single write

    这个等待事件通常只发生在一种情况,就是Oracle更新数据文件头信息时(比如发生 Checkpiont)。

    当这个等待事件很明显时,要考虑是不是数据库中的数据文件数量太大,导致Oracle需要花较长的时间来做所有文件头的更新操作(Checkpoint)。

1 这个等待事件包含3个参数:
2 File#----需要更新的数据块所在数据文件的文件号。
3 Block#----需要更新的数据块号。
4 Blocks----需要更新的数据块数目(通常来说应该等于1)。


10、direct path read

    这个等待事件发生在会话将数据块直接读取到PGA当中而不是SGA中的情况,这些被读取的数据通常是这个会话私有的数据,所以不需要放到SGA作为共享数据,因为这样做没有意义,这些数据通常是来自于临时段上的数据,比如一个会话中SQL的排序数据,

    并行执行过程中间产生的数据,以及Hash join,Merge join产生的排序数据,因为这些数据只对当前会话的SQL操作有意义,所以不需要放到SGA当中。

    当发生direct path read等待事件时,意味着磁盘上有大量的临时数据产生,比如排序,并行执行等操作,或者意味着PGA中空闲空间不足

1 这个等待事件包含3个参数:
2 descriptoraddress----一个指针,指向当前会话正在等待的一个directread I/O。
3 first dba---- descriptoraddress中最旧的一个I/O数据块地址。
4 blockcnt----descriptoraddress上下文中涉及到的有效地buffer数量。


11、direct path write

    这个等待事件和direct path read正好相反,是会话将一些数据从PGA中直接写入到磁盘文件上,而不经过SGA。

这种情况通常发生在:

a、使用临时表空间排序(内存排序不足)。

b、数据的直接加载(使用append方式加载数据)。

c、并行DML操作。

1 这个等待事件包含3个参数:
2 descriptoraddress----一个指针,指向当前会话正在等待的一个direct I/O。
3 first dba---- descriptoraddress中最旧的一个I/O数据块地址。
4 blockcnt----descriptoraddress上下文中涉及到的有效地buffer数量。


12、enqueue

    enqueue这个词其实是lock(锁)的另一个描述语,我们可以把它作为lock 来理解就会好理解的锁。当我们在AWR报告中发现长时间的enqueue等待事件时,说明数据库中出现了阻塞和等待,我们可以关联AWR报告中Enqueue Activity部分来确定是哪一种锁定出现了长时间等待。

1 这个等待事件包含2个参数:
2 Name----enqueue的名称和类型。
3 Mode---- enqueue的模式。

Oracle的enqueue有以下类型,第一列为enqueue的缩写,第二列是对缩写的解释:

01 BL, BufferCacheManagement
02 BR, Backup/Restore
03 CF, ControlfileTransaction
04 CI, Cross-instance CallInvocation
05 CU, BindEnqueue
06 DF, Datafile
07 DL, DirectLoaderIndex Creation
08 DM, DatabaseMount
09 DR, DistributedRecoveryProcess
10 DX, DistributedTransaction
11 FP, FileObject
12 FS, FileSet
13 HW, High-WaterLock
14 IN, Instance Number
15 IR, Instance Recovery
16 IS, Instance State
17 IV, LibraryCacheInvalidation
18 JI, EnqueueusedduringAJVsnapshotrefresh
19 JQ, JobQueue
20 KK, RedoLog"Kick"
21 KO, MultipleObjectCheckpoint
22 L[A-P], LibraryCacheLock
23 LS, LogStartorSwitch
24 MM, MountDefinition
25 MR, MediaRecovery
26 N[A-Z], LibraryCachePin
27 PE, ALTERSYSTEMSETPARAMETER=VALUE
28 PF, PasswordFile
29 PI, ParallelSlaves
30 PR, ProcessStartup
31 PS, ParallelSlaveSynchronization
32 Q[A-Z], RowCache
33 RO, ObjectReuse
34 RT, RedoThread
35 RW, RowWait
36 SC, SystemCommitNumber
37 SM, SMON
38 SN, SequenceNumber
39 SQ, SequenceNumberEnqueue
40 SR, SynchronizedReplication
41 SS, SortSegment
42 ST, SpaceManagementTransaction
43 SV, SequenceNumberValue
44 TA, TransactionRecovery
45 TC, ThreadCheckpoint
46 TE, ExtendTable
47 TM, DMLEnqueue
48 TO, TemporaryTableObjectEnqueue
49 TS, TemporarySegment(alsoTableSpace)
50 TT, TemporaryTable
51 TX, Transaction
52 UL, User-definedLocks
53 UN, UserName
54 US, UndoSegment, Serialization
55 WL, BeingWrittenRedoLog
56 XA, Instance AttributeLock
57 XI, Instance RegistrationLock

Oracle的enqueue包含以下模式:

模式代码 解释

1 1 Null mode
2 2 Sub-Share
3 3 Sub-Exclusive
4 4 Share
5 5 Share/Sub-Exclusive
6 6 Exclusive

可以使用下面的SQL得到当前会话等待的enqueue名称和类型:

1 select sid, chr(bitand(p1, -16777216)/16777215)||chr(bitand(p1,16711680)/65535) "Name",
2 (bitand(p1, 65535))"Mode" from v$session_wait where event=‘enqueue‘;
3 SID Name Mode
4 --- ---- ----
5 64  TX     6


13、free buffer waits

     当一个会话将数据块从磁盘读到内存中时,它需要到内存中找到空闲的内存空间来存放这些数据块,当内存中没有空闲的空间时,就会产生这个等待; 除此之外,还有一种情况就是会话在做一致性读时,需要构造数据块在某个时刻的前映像(image),此时需要申请内存块来存放这些新构造的数据块,如果内存中无法找到这样的内存块,也会发生这个等待事件。

     当数据库中出现比较严重的free bufferwaits等待事件时,可能的原因是:

 a、Data buffer太小,导致空闲空间不够。

 b、内存中的脏数据太多,DBWR无法及时将这些脏数据写到磁盘中以释放空间。

1 这个等待事件包含2个参数:
2 File#----需要读取的数据块所在数据文件的文件号。
3 Block#----需要读取的数据块块号。


14、latch free

    在10g之前的版本里,latch free等待事件代表了所有的latch 等待,而在10g中,一些常用的latch事件已经被独立出来:

01 SQL>select name from v$event_name where name like ‘latch%‘orderby 1;
02 NAME
03 ----------------------------------------------------------------
04 latch activity
05 latch free
06 latch: ChangeNotificationHashtable latch
07 latch: In memoryundolatch
08 latch: KCLgcelementparentlatch
09 latch: MQLTrackingLatch
10 latch: UndoHintLatch
11 latch: cachebufferhandles
12 latch: cachebufferschains
13 latch: cachebufferslru chain
14 latch: checkpointqueuelatch
15 latch: enqueuehashchains
16 latch: gcsresource hash
17 latch: gesresource hashlist
18 latch: library cache
19 latch: library cachelock
20 latch: library cachepin
21 latch: messages
22 latch: objectqueueheaderheap
23 latch: objectqueueheaderoperation
24 latch: parallelqueryallocbuffer
25 latch: redo allocation
26 latch: redo copy
27 latch: redo writing
28 latch: row cacheobjects
29 latch: sessionallocation
30 latch: sharedpool
31 latch: undoglobaldata
32 latch: virtualcircuitqueues
33 29rows selected.
34 SQL>

所以latch free等待事件在10g中并不常见,而是以具体的Latch等待事件出现。

1 这个等待事件包含3个参数:
2 Address----会话等待的latch 地址
3 NNumber----latch 号,通过这个号,可以从v$latchname 视图中找到这个latch 的相
4 关信息。
5 select *
6 from v$latchname
7 where latch#=number;
8 Tries----会话尝试获取latch的次数,


15、library cache lock

     这个等待事件发生在不同用户在共享池中由于并发操作同一个数据库对象导致的资源争用的时候,比如当一个用户正在对一个表做DDL操作时,其他的用户如果要访问这张表,就会发生library cache lock 等待事件,它要一直等到DDL操作完毕后,才能够继续操作;

1 这个等待事件包含4个参数:
2 Handleaddress---- 被加载的对象的地址。
3 Lockaddress-----锁的地址。
4 mode----被加载对象的数据片段。
5 namespace----被加载对象在v$db_object_cache视图中namespace的名称。


16、library cache pin

     这个等待事件和labrary cache lock 一样是发生在共享池中并发操作引起的等待事件,通常来讲,如果Oracle要对一些pl/sql或者视图这样的对象做重新编译时,需要将这些对象pin到共享池中,如果此时这个对象被其他的用户持有,就会产生一个labrary cache pin的等待。

1 同样的,这个等待事件包含4个参数:
2 Handleaddress---- 被加载的对象的地址。
3 Lockaddress-----锁的地址。
4 mode----被加载对象的数据片段。
5 namespace----被加载对象在v$db_object_cache视图中namespace的名称。


17、log file parallel write

     后台进程LGWR负责将log buffer当中的数据写到REDO文件中,以重用log buffer的数据,如果每个REDOLOG组里面有2个以上的成员,那么LGWR进程会并行的将REDO信息写入这些文件中。

     如果数据库中出现这个等待事件的瓶颈,主要的原因可能是磁盘I/O性能不够或者REDO文件的分布导致了I/O的争用,比如同一个组的REDO成员文件放在相同的磁盘上。

1 这个等待事件包含3个参数:
2 Files----操作需要写入的文件个数。
3 Blocks----操作需要写入的数据块个数。
4 Requests----操作需要执行的I/O次数。


18、log buffer space

     当log buffer当中没有可用空间来存放新产生的redo log 数据时,就会发生log buffer space等待事件,如果数据库中新产生的redo log 的数量大于LGWR写入到磁盘中的redo log 数量时,必须等待LGWR完成写入磁盘的操作,LGWR必须确保redo log 写到磁盘成功之后,才能在redo buffer当中重用这部分信息。

    如果数据库中出现大量的log bufferspace等待事件,可以考虑下面的解决方法:

a、增加redo buffer的大小。

b、提生磁盘的i/o性能。

这个等待事件没有参数。

 


19、log file sequential read

     这个等待事件通常发生在对redo log 信息的读取时,比如在

热门排行

今日推荐

热门手游