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

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

主要内容:
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. 并发统计信息收集
sql

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

不 同于以往的版本,在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:sass

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;

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

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');

 

发表在 ORACLE | 标签为 12C | 留下评论

常见的等待事件

发表于 2013 年 8 月 12 日  周应侯

一、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以后则表示等待事件的类别。


二、buffer latch

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

产生buffer latch 的等待事件的主要缘由是:

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

   二、一样的数据块被频繁访问,就是咱们一般说的热块问题。

  若是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。

 

 三、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次数。

 

四、controlfile sequential read

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

 a、备份控制文件

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

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

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

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

 

五、db file parallel read

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

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


六、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----等待的超时时间。

 

七、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----须要读取的数据块数目。

 

八、db file sequential read

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

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

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


九、db file single write

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

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

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


十、direct path read

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

    并行执行过程当中间产生的数据,以及Hash joinMerge join产生的排序数据,由于这些数据只对当前会话的SQL操做有意义,因此不须要放到SGA当中。

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

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


十一、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数量。


十二、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


1三、free buffer waits

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

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

 a、Data buffer过小,致使空闲空间不够。

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

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


1四、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的次数,


1五、library cache lock

     这个等待事件发生在不一样用户在共享池中因为并发操做同一个数据库对象致使的资源争用的时候,好比当一个用户正在对一个表作DDL操做时,其余的用户若是要访问这张表,就会发生library cache lock 等待事件,它要一直等到DDL操做完毕后,才可以继续操做;

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


1六、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的名称。


1七、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次数。


1八、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性能。

这个等待事件没有参数。

 


1九、log file sequential read

     这个等待事件一般发生在对redo log 信息的读取时,好比在线redo的归档操做,ARCH进程须要读取redo log 的信息,因为redo log 的信息是顺序写入的,因此在读取的是有也是按照顺序的方式来读取。

1 这个等待事件包含3个参数:
2 log#----发生等待时读取的redo log 的sequence号。
3 block#---- 读取的数据块号。
4 blocks---读取的数据块个数。


20、log file single write

     这个等待事件发生在更新redo log 文件的文件头时,当为日志组增长新的日志成员时或者redo log 的sequence号改变时,LGWR都会更新redo log 的文件头信息。

1 这个等待事件包含3个参数:
2 log#----写入的redo log 组的编号。
3 block#---- 写入的数据块号。
4 blocks---写入的数据块个数。


2一、log file switch (archiving needed)

    在归档模式下,这个等待事件发在在线日志切换(log file switch)时,须要切换到的在线日志尚未被归档进程(ARCH)归档完毕的时候。当在线日志文件切换到下一个日志时,须要确保下一个日志文件已经被归档进程归档完毕,不然不容许覆盖那个在线日志信息(不然会致使归档日志信息不完整)。

    出现这样的等待事件一般是因为某种缘由致使ARCH进程死掉,好比ARCH进程尝试向目的地写入一个归档文件,可是没有成功(介质失效或者其余缘由),这是ARCH进程就会死掉。若是发生这样状况,在数据库的alert文件中能够找到相关的告警信息。

这个等待事件没有参数。


2二、log file switch (checkpointin complete)

     当一个在线日志切换到下一个在线日志时,必须保证要切换到的在线日志上记录的信息(好比一些脏数据块产生的redo log)被写到磁盘上(checkpoint),这样作的缘由是,如果一个在线日志文件的信息被覆盖,而依赖这些redo信息作恢复的数据块还没有被写到磁盘上(checkpoint),此时系统down掉的话,Oracle将没有办法进行实例恢复。

    在v$log视图里记录了在线日志的状态,一般来讲在线日志有3个状态:

Active—-这个日志上面保护的信息尚未完成checkpoint。

Inactive—-这个日志上面保护的信息已经完成checkpoint。

Current—-当前的日志。

    Oracle在作实例恢复时,会使用状态为current和active的日志进行实例恢复若是系统中出现大量的log file switch (checkpointincomplete)等待事件,缘由可能日志文件过小或者日志组太少,因此解决的方式是,增日志文件的大小或者增长日志组的数量

这个等待事件没有参数。


2三、log file sync

     这是一个用户会话行为致使的等待事件,当一个会话发出一个commit命令时,LGWR进程将会将这个事务产生的redo log 从log buffer里写到磁盘上,以保证用户提交的信息被安全地记录到数据库中。

     会话发出commit指令后,须要等待LGWR将这个事务产生的redo成功写入到磁盘之后,才能够继续进行后续的操做,这个等待事件就叫作log file sync

     当系统中出现大量的log file sync等待事件时,应该检查数据库中是否有用户在作频繁的提交操做

     这种等待事件一般发生在OLTP系统上,OLTP系统中存在不少小的事务,若是这些事务频繁被提交,可能引发大量log file sync的等待事件。

1 这个等待事件包含1个参数:
2 Buffer#----redo buffer中须要被写入到磁盘中的buffer。


2四、SQL*Net break/reset to client

     当出现这个等待事件时,说明服务器端在给客户端发送一个断开链接或者重置链接的请求,正在等待客户端的响应,一般的缘由是服务器到客户端的网络不稳定致使

1 这个等待包含2个参数:
2 driverid----服务器端和客户端链接使用的协议信息。
3 break----0表示服务器端向客户端发送一个重置(reset)消息,非零表示服务器端向客 户端发送一个断开(break)消息。


2五、SQL*Net break/reset to dblink

     这个等待事件和SQL*Net break/reset to client相同。不过它表示的是数据库经过dblink访问另外一台数据库时,它们之间会创建起一个会话,这个等待事件发生的这个会话之间的通讯过程当中,一样若是出现这个等待事件,须要检查两台数据库之间的通讯问题。

1 这个等待事件包含2个参数:
2 driver driverid----服务器端和另外一个服务器端链接使用的协议信息。
3 break----0表示服务器端向另外一个服务器端发送一个重置(reset)消息,非零表示
4 一个 断开(break)消息。


2六、SQL*Net message from client

     这个等待事件基本上算是最多见的一个等待事件了,当一个会话创建成功后,客户端会向服务器端发送请求,服务器端处理完客户端请求后,将结果返回给客户端,并继续等待客户端的请求,这时候就会产生SQL*Netmessagefrom client等待事件

    很显然,这是一个空闲等待,若是客户端再也不向服务器端发送请求,服务器端将一直处

于这个等待事件状态。

1 这个等待事件包含2个参数:
2 driverid----服务器端和客户端链接使用的协议信息。
3 #bytes----服务器端收到的来自客户端消息的字节数。


2七、SQL*Net message from dblink

      这个等待事件和SQL*Net message from client相同,不过它表示的是数据库经过dblink访问另外一台数据库时,它们之间会创建起一个会话,这个等待事件发生的这个会话之间的通讯过程当中。

这个等待事件也是一个空闲等待事件。

1 这个等待事件包含2个参数:
2 driverid----服务器端和服务器端链接使用的协议信息。
3 #bytes----服务器端经过dblink收到的来另外一个服务器端消息的字节数。


2八、SQL*Net message to client

     这个等待事件发生在服务器端向客户端发送消息的时候。当服务器端向客户端发送消息产生等待时,可能的缘由是用户端太繁忙,没法及时接收服务器端送来的消息,也多是网络问题致使消息没法从服务器端发送到客户端

这个等待事件包含2个参数:

driverid—-服务器端和服务器端链接使用的协议信息。

#bytes—-服务器端向客户端发送消息的字节数。


2九、SQL*Net message to dblink

    这个等待事件和SQL*Netmessageto client相同,不过是发生在数据库服务器和服务器之间的等待事件,产生这个等待的缘由多是远端服务器繁忙没法及时接收发送过来的消息,也多是服务器之间网络问题致使消息没法发送过来。

1 这个等待事件包含2个参数:
2 driverid----服务器端和服务器端链接使用的协议信息。
3 #bytes----服务器端经过dblink发送给另外一个服务器消息的字节数。


30、SQL*Net more data from client

    服务器端等待用户端发出更多的数据以便完成操做,好比一个大的SQL文本,致使一个SQL*Net数据包没法完成传输,这样服务器端会等待客户端把整个SQL文本发过来再作处理,这时候就会产生一个SQL* Net more data from client等待事件。

1 这个等待事件包含2个参数:
2 driverid----服务器端和服务器端链接使用的协议信息。
3 #bytes----服务器端从客户端接收到消息的字节数。


3一、SQL*Net more data from dblink

     在一个分布式事务中,SQL分布在不一样的数据库中执行,远程数据库执行完毕后将结果经过dblink返给发出SQL的数据库,在等待数据从其余数据库中经过dblink传回的过程当中,若是数据在远程数据库上处理时间好久,或者有大量的结果集须要返回,或者网络性能问题都会产生SQL*Netmoredatafrom dblink等待事件,它的意思是本地数据库须要等到全部的数据从远端处理完毕经过dblink传回后,才能够在本机继续执行操做

1 这个等待事件包含2个参数:
2 driverid----服务器端和服务器端链接使用的协议信息。
3 #bytes----服务器端经过dblink接收到来自另外一个服务器消息的字节数。


3二、SQL*Net more data to client

     当服务器端有太多的数据须要发送给客户端时,可能会产生SQL*Net more data to client等待事件; 也可能因为网络问题致使服务器端没法及时的将信息或处理结果发送给客户端时,一样会产生这个等待。

1 这个等待事件包含2个参数:
2 driver driverid----服务器端和客户端链接使用的协议信息。
3 #bytes----服务器端向客户端发送消息的字节数。


3三、SQL*Net more data to dblink

     这个等待事件和SQL*Net more data to client等待事件基本相同,只不过等待发生在分布式事务中,即本地数据库须要将更多的数据经过dblink发送给远程数据库,因为发送的数据太多或者网络性能问题,就会出现SQL*Netmoredatato dblink等待事件。

1 这个等待事件包含2个参数:
2 driverid----服务器端和服务器端链接使用的协议信息。
3 #bytes----服务器端经过dblink向另外一个服务器发送消息的字节数。

 

发表在 troubleshooting | 标签为 WAIT EVENT | 留下评论

Library Cache 诊断:Lock, Pin 以及 Load Lock (文档 ID 1548524.1)

发表于 2013 年 8 月 11 日  周应侯

文档中将提供关于 Library cache lock, Library cache pin 与 Library cache load lock 的一些简明的知识。

什么是”Library cache lock” ?
什么是”Library cache pin” ?
为何须要这两种不一样类型的锁?
减小Library Cache 竞争的通常建议
如何下降 library cache lock 等待
如何下降 library cache pin 等待
什么是 Library cache load lock?
如何减小 Library cache load lock
Library cache pin 与 library load lock 是什么关系

什么是”Library cache lock” ?

  • 这个事件控制对 library cache 的并发使用。 它获取一个对象句柄(object handle)上的锁,从而:

    定位 library cache 中的一个对象一样也须要这个锁。
    在解析或编译 SQL 或 PL/SQL 语句期间,咱们须要得到被引用的数据库对象(表,视图,过程,函数,包,包体,触发器,索引,聚簇,同义词)的 library cache lock;这个锁在解析与编译结束时会被释放。

    cursor(SQL 与 PL/SQL 区),管道(pipes)和其它的瞬时(transient)对象不使用这个锁。
    Library cache lock 上的死锁不会被自动检测到,对其的操做是同步进行的。

    参数:

    • handle address
      对象地址

    • lock address
      锁地址。它与 latch 与 enqueue 不一样,它是一个 State Object。

    • Mode
      申请锁的级别

    • Namespace
      对象使用的 namespace, 取自于 V$DB_OBJECT_CACHE。

      什么是”Library cache pin” ?

    • 这个使用者能够长时间地维护一个依赖对象(例如,其它使用者不能更改这个对象)。

    • 一个使用者能够防止其它使用者访问同一个对象。

    • 这 个事件管理 library cache 并发。Pin 住一个对象会使它使用的 heap 被载入到内存中。若是一个使用者想要修改或检查这个对象,它必须在得到 lock 以后再取得一个 pin。Pin 能够用 NULL, SHARE, EXCLUSIVE 模式得到,而且能够看作是一种特殊的 lock。等待”library cache pin”意味着这个 PIN 正被某个其它 session 以不兼容的模式持有。

      访 问当前被缓存到 library cache 中的数据库对象(表,视图,过程,函数,包,包体,触发器,索引,聚簇,同义词)的时候须要得到 library cache pin; 在 library cache 中,数据库对象被缓存成两部分:句柄(handle)和对象(object); 这个锁(pin)是用来保护”object”部分的。Library cache pin 上的死锁不会被自动检测到,对其的操做是同步进行的。

      注意:在10g之后,”library cache pin”已经被 mutex 取代。
      参见:Note 1298015.1 WAITEVENT: “cursor: pin S wait on X” Reference Note


    • 为何须要这两种不一样类型的锁?

      Lock 与 pin 都用于访问在 library cache 中的对象。Lock 管理不一样进程间的并发,pin 则管理缓冲区的一致性。为了访问一个对象,进程必须首先锁定(lock)这个对象的句柄(handle),而后它本身 pin 住对象的内存堆。

      Lock 与 pin 请求会一直等待直到得到为止,这是一个引发争用的可能的缘由,由于它没有 NOWAIT 请求模式。

      经过得到一个在对象句柄上的锁,一个进程能防止其它进程访问这个对象,甚至不能够查看它的类型。它还能在维护对象依赖关系的同时不阻止其它进程访问这个对象。获取一个 lock 一样也是在缓存中查找对象的惟一途径。查找并锁住对象是在一个操做中完成的。

      若是一个进程想检查或修改一个对象,那么它必须得到一个在这个对象上的 pin (得到了在句柄上的锁以后)。Pin这个动做会将相应对象的信息载入到内存,若是以前没有的话,同时还能确保这些信息保留在内存直到 pin 被释放。

      Oracle 在分析/编译 Package/Procedure/Function/View 时须要 Library Cache Lock 和 Library Cache Pin。这是为了确保在分析/编译期间, 没有其它人能够对这些对象的定义进行改变,或者删除、重建这个对象。

      当 一个 SQL 语句被一个 session 硬解析时,这个 session 须要得到一个 library cache lock 以便阻止其它 session 去访问或修改同一个对象。若是这个事件等待很长时间。这代表可能 shared pool 太小或常常发生对象被 flush 出去的清醒。还有,这代表数据库对象被常常修改。

      除了硬解析,若是一个 session 要更改被 SQL 语句引用的对象的定义或对其作任何更改,就必须得到一个 library cache lock 和 library cache pin。须要 Pin 的缘由是须要加载数据字典信息到内存中来修改这个对象。

      Note 34579.1 WAITEVENT: “library cache pin” Reference Note


    • 减小Library Cache 竞争的通常建议

      下边会介绍一下解决不一样竞争的不一样的方法。可是,不少时候这些现象都是因为 SQL 语句的版本数形成的。若是您看到了任何跟 library cache 相关的竞争,应该马上检查 AWR Report 确保没有版本数很高(好比几百)的 SQL 语句。

      若是有的话请参见如下文档解决:

      Document 296377.1 Troubleshooting: High Version Count Issues


    • 如何下降 library cache lock 等待

      我 们首先要确认的是 library cache 的竞争是整个系统层面的仍是只发生在某个或某些 SQL 语句上。这个”library cache lock”是被一个特定的 SQL 持有很长的时间吗?或者老是在等待某个特定的对象?仍是说这个锁在短期内被请求的次数不少从而形成的竞争?

      若是问题是在整个系统层面发生的,通常来讲是因为 shared pool 过小或 SQL 语句不共享形成的。一些解决竞争的方法:

      若是您发现是某条或某些SQL产生的问题,那么须要检查为何它持有锁的时间会那么长。
      如下文档能够用来找到谁在持有锁以及在哪一个对象上:

      Note 122793.1 How to Find which Session is Holding a Particular Library Cache Lock

      • 增大 shared pool 从而减小 reload 的次数,这是由于 shared pool 太小会形成获取锁的时间加长。

      • 经过将 cursor_sharing 设置为 similar 或 force 来使 SQL 语句共享。
        须要当心的是这样作可能会改变SQL的执行计划,因此作以前须要作完整的测试。

      • 在系统不繁忙的时候作统计信息的收集或其它维护做业,从而下降无效化(invalidation)的次数。


    • 如何下降 library cache pin 等待

      若是”library cache pin”等待的时间很长那么很重要的一点就是判断是只有一两个 process 在等待仍是有不少的 process 都在等待。

      • 若是说只是一两个 process 被另外一个 process 阻塞的话,那么须要检查持有这个 pin 的 process 为何这么长时间不释放。

      • 若是说等待是大范围的那么说明 shared pool 须要优化。

        Note 62143.1 Troubleshooting: Tuning the Shared Pool and Tuning Library Cache Latch Contention


    • 什么是 Library cache load lock?

      Session 尝试去查找数据对象上的 load lock,以便能加载这个对象。

      Load lock 必定是以排它模式得到,以便没有其它进程能够加载同一个对象。若是没法得到 load lock,那么 session 将等待这个事件,直到其变为可用状态。

      等待时间: 3秒(PMON 会等待1秒)

      参数:

      • object address
        对象的地址

      • lock address
        锁的地址


    • 如何减小 Library cache load lock

      若是一个对象不在内存中,那么咱们不能对其申请 library cache lock。
      所以,须要将这个对象加载到内存中。
      而后,session 尝试找到数据库对象的 load lock,以便它能载入这个对象。
      为了阻止多进程同时请求加载同一个对象,其它一样请求的 session 将等待 library cache load lock 由于这个对象正在被加载到内存中。

      等待 library cache load lock 是因为对象在内存中是不存在的。
      Library cache 中的对象不存在,是因为 shared pool 太小引发的频繁从新装载,或太多的硬解析缘于不共享的 SQL。

      避免这种等待的一般建议:

      Note:94036.1 Init.ora Parameter “CURSOR_SHARING” Reference Note

      • 设置 cursor_sharing 为 force(减小硬解析)。—可能改变执行计划与查询的性能,因此要做充分的测试。

      • 增长 session cached cursors(避免 cursor 被刷出 shared pool)

      • 增长 shared pool(避免 reload).


      • Library cache pin 与 library load lock 是什么关系

        Library cache pin 和 load lock 可能出如今对 PL/SQL, views, types 等的编译与重编译期间。这种编译老是显式的(好比应用安装,升级,打补丁)。可是对象重编译也可能发生在对象失效期间。

        在 处理那些“奇怪“的 library cache pin 和 load lock 等待时,咱们须要检查为何对象失效了。颇有可能失效是因为某些操做修改了它所依赖的对象的”LAST_DDL”。一般来讲这些操做包括对象维护操做,比 如 ALTER, GRANT, REVOKE, replacing views 等等。还有就是收集 optimizer statistics 也会形成 cursor 失效,进而致使 library cache 的重装载。这个现象在 Oracle Server Application Developer’s Guide 的object dependency maintenance 部分有描述。

        对 象失效之后,Oracle 尝试在第一次访问这个对象时去重编译它。有些状况下,若是其它 session 已经 pin 住这个对象,可能就会出现问题。 很显然,在有大量活跃用户与复杂依赖关系(例如,不少交叉依赖的 packages 或package bodies)的状况下更容易出现问题。有些时候对对象的编译会持续数小时从而阻止其它 session 对其的访问。

        在 library cache dump, level 10 能够看到:
        查找 ALTER … COMPILE 语句和 lock=X 或 pin=X 的 objects/handles.


      • 提示

        • Load lock老是以排它模式得到的。
          若是 session load lock 繁忙,session 将一直等待,直到锁变成可用。

        • 需 要频繁使用的 stored PL/SQL 所依赖的对象,对其 altering, granting, evoking 操做须要特别当心。实际上,解决这种问题很大程度上依赖于应用程序和系统维护的时间。应用程序开发者须要考虑某些决定可能会对应用程序的可扩展性及性能产 生负面影响。

      REFERENCES

      NOTE:34579.1 - WAITEVENT: “library cache pin” Reference Note
      NOTE:62143.1 - Troubleshooting: Tuning the Shared Pool and Tuning Library Cache Latch Contention
      NOTE:7423411.8 - Bug 7423411 – Process may hang waiting for “library cache load lock” with no holder
      NOTE:10018789.8 - Bug 10018789 – Spin in kgllock / DB hang with high library cache lock waits
      NOTE:1298015.1 - WAITEVENT: “cursor: pin S wait on X” Reference Note
      NOTE:296377.1 - Troubleshooting: High Version Count Issues
      NOTE:7706138.8 - Bug 7706138 – Process may hang waiting for “library cache load lock” with no holder
      NOTE:94036.1 - Init.ora Parameter “CURSOR_SHARING” Reference Note
      NOTE:9675816.8 - Bug 9675816 – Self deadlock with ‘library cache lock’ waits / OERI:17059
      NOTE:122793.1 - How to Find which Session is Holding a Particular Library Cache Lock

      发表在 troubleshooting | 标签为 Library Cache | 留下评论

      AWK经典练习及解答

      发表于 2013 年 8 月 9 日  周应侯

      数据脚本名称为lab3.data

      01 Mike Harrington:(510) 548-1278:250:100:175
      02 Christian Dobbins:(408) 538-2358:155:90:201
      03 Susan Dalsass:(206) 654-6279:250:60:50
      04 Archie McNichol:(206) 548-1348:250:100:175
      05 Jody Savage:(206) 548-1278:15:188:150
      06 Guy Quigley:(916) 343-6410:250:100:175
      07 Dan Savage:(406) 298-7744:450:300:275
      08 Nancy McNeil:(206) 548-1278:250:80:75
      09 John Goldenrod:(916) 348-4278:250:100:175
      10 Chet Main:(510) 548-5258:50:95:135
      11 Tom Savage:(408) 926-3456:250:168:200
      12 Elizabeth Stachelin:(916) 440-1763:175:75:300

      该数据中包含姓名、电话号码、以及在最近3个月中的竞选捐款数额
      一、打印全部的电话号码

      01 [root@zhouyinghou awk]# awk -F: '{print $2}' lab3.data
      02 (510) 548-1278
      03 (408) 538-2358
      04 (206) 654-6279
      05 (206) 548-1348
      06 (206) 548-1278
      07 (916) 343-6410
      08 (406) 298-7744
      09 (206) 548-1278
      10 (916) 348-4278
      11 (510) 548-5258
      12 (408) 926-3456
      13 (916) 440-1763

      二、打印Dan的电话号码

      1 [root@zhouyinghou awk]# awk -F: '/^Dan/{print $2}' lab3.data
      2 (406) 298-7744

      三、打印Susan的姓名和电话号码

      1 [root@zhouyinghou awk]# awk -F: '/^Susan/{print $1,$2}' lab3.data
      2 Susan Dalsass (206) 654-6279

      四、打印全部以D开头的姓氏

      1 [root@zhouyinghou awk]#awk -F'[: ]' '$2 ~ /^D/{print $2}' lab3.data
      2 Dobbins
      3 Dalsass

      五、打印全部以C或者E开头的名字

      1 [root@zhouyinghou awk]# awk '/^[CE]/{print $1}' lab3.data
      2 Christian
      3 Chet
      4 Elizabeth

      或者

      1 awk -F'[: ]' '$1 ~ /^[CD]/{print $1}' lab3.data

      六、打印全部只包含4个字符的名字

      1 [root@zhouyinghou awk]# awk '{if(length($1)==4)print $1}' lab3.data
      2 Mike
      3 Jody
      4 John
      5 Chet

      或者

      1 awk '$1 ~ /^....$/{print $1}' lab3.data

      七、打印全部区号为916的人的名字

      1 [root@zhouyinghou awk]# awk '{if($2~/(916)/)print $1}' lab3.data
      2 Guy
      3 John
      4 Elizabeth

      八、打印Mike的资助金额,每个值都须要用$符号开头,例如“$250$100$175”

      1 [root@zhouyinghou awk]# awk -F: '{if ($1~"Mike") print "$"$3"$"$4"$"$5}' lab3.data
      2 $250$100$175

      九、打印全部的姓,后面跟一个逗号和名

      01 [root@zhouyinghou awk]# awk -F: '{print $1}' lab3.data|awk '{print $1","$2}'
      02 Mike,Harrington
      03 Christian,Dobbins
      04 Susan,Dalsass
      05 Archie,McNichol
      06 Jody,Savage
      07 Guy,Quigley
      08 Dan,Savage
      09 Nancy,McNeil
      10 John,Goldenrod
      11 Chet,Main
      12 Tom,Savage
      13 Elizabeth,Stachelin

      十、编写一个名为facts的脚本,并完成下面的工做

      a、打印全部姓氏为Savage的人的全名和电话号码
      b、打印Chet的资助金额
      c、打印全部在第一个月资助了250美圆的人

      1 #!/bin/bash
      2 #filename=facts
      3 $2 ~ /Savage/{print $1,$2,$3,$4}
      4 /^Chet/ {print $5,$6,$7}
      5 $5 ~ /^250/ {print $1,$2}
      01 [root@zhouyinghou awk]# awk -F'[: ]' -f facts lab3.data
      02 Mike Harrington
      03 Susan Dalsass
      04 Archie McNichol
      05 Jody Savage (206) 548-1278
      06 Guy Quigley
      07 Dan Savage (406) 298-7744
      08 Nancy McNeil
      09 John Goldenrod
      10 50 95 135
      11 Tom Savage (408) 926-3456
      12 Tom Savage

       

      发表在 LinuxSHELLUnix | 标签为 AWKSHELLUNIX | 留下评论

      Dataguru《ORACLE性能优化》第二课 LOCK

      发表于 2013 年 8 月 3 日  周应侯

      为何会有锁
      没有并发就没有锁!

      Oracle中锁的分类
      Enqueues—队列类型的锁,一般和业务相关的。
      Latches —系统资源方面的锁,好比内存结构,SQL解析……

      锁的原则
       只有被修改时,行才会被锁定。
       当一条语句修改了一条记录,只有这条记录上被锁定,在Oracle数据库中不存在锁升级。
       当某行被修改时,它将阻塞别人对它的修改。
       当一个事务修改一行时,将在这个行上加上行锁(TX),用于阻止其它事务对相同行的修改。
       读永远不会阻止写。
       读不会阻塞写,但有惟一的一个例外,就是select …for update。
       写永远不会阻塞读。
       当一行被修改后,Oracle经过回滚段提供给数据的一致性读。

      Oracle锁的类型

      01 SQL> select type,name from V$lock_type;
      02 TYPE NAME
      03 ---------- ----------------------------------------
      04 WM WLM Plan Operations
      05 CI Cross-Instance Call Invocation
      06 PR Process Startup
      07 AK GES Deadlock Test
      08 DI GES Internal
      09 RM GES Resource Remastering
      10 PE Parameter
      11 PG Global Parameter
      12 FP File Object
      13 RE Block Repair/Resilvering
      14 KD Scheduler Master DBRM
      15 KM Scheduler
      16 ....
      17 155 rows selected.

       TM锁和TX锁
       TM 表锁,发生在insert,update,delete以及select for update操做时,目的是保证操
      做可以正常进行,而且阻止其它人对表执行DDL操做。
       TX锁 事务锁(行锁)对于正在修改的数据,阻止其它会话进行修改。

      TM锁的几种模式—-lock mode
       Row Share (RS) –2
      This lock, also called a subshare table lock (SS), indicates that the transaction holding the lock on the table has locked rows in the table and
      intends to update them. A row share lock is the least restrictive mode of table lock, offering the highest degree of concurrency for a table.
       Row Exclusive Table Lock (RX)—3
      This lock, also called a subexclusive table lock (SX), generally indicates that the transaction holding the lock has updated table rows or issued
      SELECT … FOR UPDATE. An SX lock allows other transactions to query, insert, update, delete, or lock rows concurrently in the same table.
      Therefore, SX locks allow multiple transactions to obtain simultaneous SX and subshare table locks for the same table.
       Share Table Lock (S) –4
      A share table lock held by a transaction allows other transactions to query the table (without using SELECT … FOR UPDATE), but updates are
      allowed only if a single transaction holds the share table lock. Because multiple transactions may hold a share table lock concurrently,
      holding this lock is not sufficient to ensure that a transaction can modify the table.
       Share Row Exclusive Table Lock (SRX) —5
      This lock, also called a share-subexclusive table lock (SSX), is more restrictive than a share table lock. Only one transaction at a time can
      acquire an SSX lock on a given table. An SSX lock held by a transaction allows other transactions to query the table (except for SELECT … FOR
      UPDATE) but not to update the table.
       Exclusive Table Lock (X) —6
      This lock is the most restrictive, prohibiting other transactions from performing any type of DML statement or placing any type of lock on the
      table.

      TM锁几种模式的互斥关系

      RI锁—基于引用关系的锁定
       当对具备主外键关系的表作DML操做时,锁定不仅仅发生在操做表上,相应的引用表
      上也可能加上相应的锁定。

      死锁
       两个会话互相持有对方资源致使死锁。

      结论–锁定是一个开发的范畴
       经过锁定,能够达到预期的业务需求。
       经过对业务深刻的分析,能够最大程度的避免没必要要锁定的发生。

      V$LOCK
       V$LOCK列出Oracle 服务器当前拥有的锁以及未完成的锁或栓锁请求。若是你觉着session在等待等待事件队列那你应该检查本视图。若是你发现session在等待一个锁。那么按以下前后顺序:
      1.使用V$LOCK找出session持有的锁。
      2.使用V$SESSION找出持有锁或等待锁的session执行的sql语句。
      3.使用V$SESSION_WAIT找出什么缘由致使session持有锁堵塞。
      4.使用V$SESSION获取关于持有锁的程序和用户的更多信息。

      V$LOCK定义:

      01 Name           Null        Type   
      02 ----------   ----------   ----------
      03 ADDR                       RAW(0)
      04 KADDR                      RAW(0)
      05 SID                        NUMBER
      06 TYPE                       VARCHAR2(2)
      07 ID1                        NUMBER
      08 ID2                        NUMBER
      09 LMODE                      NUMBER
      10 REQUEST                    NUMBER
      11 CTIME                      NUMBER
      12 BLOCK                      NUMBER

       V$LOCK中的经常使用列
      ·SID:表示持有锁的会话信息。
      ·TYPE:表示锁的类型。值包括TM和TX等。
      ·LMODE:表示会话等待的锁模式的信息。用数字0-6表示,和表1相对应。
      ·REQUEST:表示session请求的锁模式的信息。
      ·ID1,ID2:表示锁的对象标识。

      公共锁类型

        在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

         当Oracle执行DML语句时,系统自动在所要操做的表上申请TM类型的锁。当TM锁得到后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁 标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性便可,大大提升了系统的效率。TM锁包括了 SS、SX、S、X等多种模式,在数据库中用0-6来表示。不一样的SQL操做产生不一样类型的TM锁,以下表1。

      TX:行级锁,事务锁
      ·在改变数据时必须是排它模式(mode 6)。
      ·每个活动事务都拥有一个锁。它将在事务结束(commit/rollback)时释放。
      ·若是一个块包括的列被改变而没有ITL(interested transaction list)槽位(entries),那么session将锁置于共享模式(mode 4)。当session得到块的ITL槽位时释放。
      ·当一个事务首次发起一个DML语句时就得到一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行DML语句时,第一个会话在该条记录上加锁,其余的会话处于等待状态。当第一个会话提交后,TX锁被释放,其余会话才能够加锁。
      ·指出回滚段和事务表项

       按下列项以免竞争:
        ·避免TX-6类型竞争,须要根据您的应用而定。
        ·避免TX-4类型竞争,能够考虑增长对象INITRANS参数值。

      TM:表级锁

      ·数据库执行任何DDL语句时必须是排它模式;例如,alter table,drop table。
      ·执行像insert,update,delete这类DML语句时处于共享模式。它防止其它session对同一个对象同时执行ddl语句。
      ·任何对象拥有正被改变的数据,TM锁都将必须存在。
      ·锁指向对象。

      在TM队列避免竞争,能够考虑屏蔽对象表级锁,屏蔽表级锁防止对象执行任何ddl语句。

      示例:如何查找锁并解锁
       

      view source

      01 session 289:
      02
      03 SQL> select distinct sid from v$mystat;
      04
      05        SID
      06 ----------
      07        289
      08
      09 SQL> update zyh set name = upper(name) where id = 1;
      10
      11 1 row updated.
      12
      13 session 282:
      14
      15 SQL> select distinct sid from v$mystat;
      16
      17        SID
      18 ----------
      19        282
      20
      21 SQL> update zyh set name = lower(name) where id = 1;
      22 hang住了
      23
      24 处理过程:
      25 查看是否有session阻塞:
      26 SQL> select * from v$lock where BLOCK = 1;
      27
      28 ADDR     KADDR           SID TY        ID1        ID2      LMODE    REQUEST
      29 -------- -------- ---------- -- ---------- ---------- ---------- ----------
      30      CTIME      BLOCK
      31 ---------- ----------
      32 3E30C0A4 3E30C1C0        289 TX     589833        126          6          0
      33        174          1
      34
      35 查看TX锁的SID与Serial#:
      36 SQL> select sid,serial#,username,state,blocking_session_status,blocking_session from v$session where event like '%TX%';
      37
      38        SID    SERIAL# USERNAME                       STATE
      39 ---------- ---------- ------------------------------ -------------------
      40 BLOCKING_SE BLOCKING_SESSION
      41 ----------- ----------------
      42        282         13 SYS                            WAITING
      43 VALID                    289
      44
      45 临时KILL这个session:
      46
      47 第一:kill掉282,13,则是kill掉被block的session。
      48 alter system kill session '282,13';
      49 第二:kill掉289,则是kill掉以前block别人的session。
      50 所以经过前面的282,13所查到的SQL语句,则是后面运行被等待的SQL语句,而不是阻塞别人的SQL语句。
      51
      52 查找相应的SQL语句:
      53
      54 SQL>  select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL" from v$session a, v$lock b, v$sqltext c  where a.username is not null and a.lockwait = b.kaddr  and c.hash_value =a.sql_hash_value;
      55
      56 USERNAME       MACHINE    SID    SERIAL#     Seconds  ID1     SQL   
      57 ------------------ ------------------ ---------- ---------- ----------   ---------  ------------------------
      58
      59 SYS         prod.localdomain   282          13        339     589833 update zyh set name = lower(name) where id = 1
      相关文章
      相关标签/搜索