Oracle 复杂用户密码规则设置

在ORACLE中默认的密码规则是很宽松的,多么简单的密码都是可以被设置的。但是在一些对安全很敏感的环境下,我们最好开启ORACLE的复杂密码规则的功能。

下面我们来看看默认的ORACLE密码规则是什么样的:

[ora9i@db ora9i]$ sqlplus "/ as sysdba"
SQL*Plus: Release 9.2.0.8.0 - Production on Mon Apr 8 18:57:47 2013
Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> select * from dba_profiles where resource_name='PASSWORD_VERIFY_FUNCTION';

PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------------------------------------
DEFAULT                        PASSWORD_VERIFY_FUNCTION         PASSWORD NULL

PROFILE中的PASSWORD_VERIFY_FUNCTION是对ORACLE用户进行复杂密码规则设置的参数, 参数的值被设置为进行密码规则验证的函数。

ORACLE之前已经为我们提供的一份密码规则蓝本,我们可以根据这个蓝本进行自定义的设置。

[ora9i@db ora9i]$ cat $ORACLE_HOME/rdbms/admin/utlpwdmg.sql
Rem
Rem $Header: utlpwdmg.sql 31-aug-2000.11:00:47 nireland Exp $
Rem
Rem utlpwdmg.sql
Rem
Rem  Copyright (c) Oracle Corporation 1996, 2000. All Rights Reserved.
Rem
Rem    NAME
Rem      utlpwdmg.sql - script for Default Password Resource Limits
Rem
Rem    DESCRIPTION
Rem      This is a script for enabling the password management features
Rem      by setting the default password resource limits.
Rem
Rem    NOTES
Rem      This file contains a function for minimum checking of password
Rem      complexity. This is more of a sample function that the customer
Rem      can use to develop the function for actual complexity checks that the
Rem      customer wants to make on the new password.
Rem
Rem    MODIFIED   (MM/DD/YY)
Rem    nireland    08/31/00 - Improve check for username=password. #1390553
Rem    nireland    06/28/00 - Fix null old password test. #1341892
Rem    asurpur     04/17/97 - Fix for bug479763
Rem    asurpur     12/12/96 - Changing the name of password_verify_function
Rem    asurpur     05/30/96 - New script for default password management
Rem    asurpur     05/30/96 - Created
Rem
-- This script sets the default password resource parameters
-- This script needs to be run to enable the password features.
-- However the default resource parameters can be changed based
-- on the need.
-- A default password complexity function is also provided.
-- This function makes the minimum complexity checks like
-- the minimum length of the password, password not same as the
-- username, etc. The user may enhance this function according to
-- the need.
-- This function must be created in SYS schema.
-- connect sys/<password> as sysdba before running the script
CREATE OR REPLACE FUNCTION verify_function
(username varchar2,
  password varchar2,
  old_password varchar2)
  RETURN boolean IS
   n boolean;
   m integer;
   differ integer;
   isdigit boolean;
   ischar  boolean;
   ispunct boolean;
   digitarray varchar2(20);
   punctarray varchar2(25);
   chararray varchar2(52);
BEGIN
   digitarray:= '0123456789';
   chararray:= 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
   punctarray:='!"#$%&()``*+,-/:;<=>?_';
   -- Check if the password is same as the username
   IF NLS_LOWER(password) = NLS_LOWER(username) THEN
     raise_application_error(-20001, 'Password same as or similar to user');
   END IF;
   -- Check for the minimum length of the password
   IF length(password) < 4 THEN
      raise_application_error(-20002, 'Password length less than 4');
   END IF;
   -- Check if the password is too simple. A dictionary of words may be
   -- maintained and a check may be made so as not to allow the words
   -- that are too simple for the password.
   IF NLS_LOWER(password) IN ('welcome', 'database', 'account', 'user', 'password', 'oracle', 'computer', 'abcd') THEN
      raise_application_error(-20002, 'Password too simple');
   END IF;
   -- Check if the password contains at least one letter, one digit and one
   -- punctuation mark.
   -- 1. Check for the digit
   isdigit:=FALSE;
   m := length(password);
   FOR i IN 1..10 LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(digitarray,i,1) THEN
            isdigit:=TRUE;
             GOTO findchar;
         END IF;
      END LOOP;
   END LOOP;
   IF isdigit = FALSE THEN
      raise_application_error(-20003, 'Password should contain at least one digit, one character and one punctuation');
   END IF;
   -- 2. Check for the character
   <<findchar>>
   ischar:=FALSE;
   FOR i IN 1..length(chararray) LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(chararray,i,1) THEN
            ischar:=TRUE;
             GOTO findpunct;
         END IF;
      END LOOP;
   END LOOP;
   IF ischar = FALSE THEN
      raise_application_error(-20003, 'Password should contain at least one \
              digit, one character and one punctuation');
   END IF;
   -- 3. Check for the punctuation
   <<findpunct>>
   ispunct:=FALSE;
   FOR i IN 1..length(punctarray) LOOP
      FOR j IN 1..m LOOP
         IF substr(password,j,1) = substr(punctarray,i,1) THEN
            ispunct:=TRUE;
             GOTO endsearch;
         END IF;
      END LOOP;
   END LOOP;
   IF ispunct = FALSE THEN
      raise_application_error(-20003, 'Password should contain at least one \
              digit, one character and one punctuation');
   END IF;
   <<endsearch>>
   -- Check if the password differs from the previous password by at least
   -- 3 letters
   IF old_password IS NOT NULL THEN
     differ := length(old_password) - length(password);
     IF abs(differ) < 3 THEN
       IF length(password) < length(old_password) THEN
         m := length(password);
       ELSE
         m := length(old_password);
       END IF;
       differ := abs(differ);
       FOR i IN 1..m LOOP
         IF substr(password,i,1) != substr(old_password,i,1) THEN
           differ := differ + 1;
         END IF;
       END LOOP;
       IF differ < 3 THEN
         raise_application_error(-20004, 'Password should differ by at \
         least 3 characters');
       END IF;
     END IF;
   END IF;
   -- Everything is fine; return TRUE ;  
   RETURN(TRUE);
END;
/
-- This script alters the default parameters for Password Management
-- This means that all the users on the system have Password Management
-- enabled and set to the following values unless another profile is
-- created with parameter values set to different value or UNLIMITED
-- is created and assigned to the user.
ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME 60
PASSWORD_GRACE_TIME 10
PASSWORD_REUSE_TIME 1800
PASSWORD_REUSE_MAX UNLIMITED
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LOCK_TIME 1/1440
PASSWORD_VERIFY_FUNCTION verify_function;

启用负责密码规则步骤:

--创建密码规则函数

SQL> @?/rdbms/admin/utlpwdmg.sql
Function created.
Profile altered.

SQL> select * from dba_profiles;
PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------------------------------------
DEFAULT                        COMPOSITE_LIMIT                  KERNEL   UNLIMITED
DEFAULT                        FAILED_LOGIN_ATTEMPTS            PASSWORD 3
DEFAULT                        SESSIONS_PER_USER                KERNEL   UNLIMITED
DEFAULT                        PASSWORD_LIFE_TIME               PASSWORD 60
DEFAULT                        CPU_PER_SESSION                  KERNEL   UNLIMITED
DEFAULT                        PASSWORD_REUSE_TIME              PASSWORD 1800
DEFAULT                        CPU_PER_CALL                     KERNEL   UNLIMITED
DEFAULT                        PASSWORD_REUSE_MAX               PASSWORD UNLIMITED
DEFAULT                        LOGICAL_READS_PER_SESSION        KERNEL   UNLIMITED
DEFAULT                        PASSWORD_VERIFY_FUNCTION         PASSWORD VERIFY_FUNCTION
DEFAULT                        LOGICAL_READS_PER_CALL           KERNEL   UNLIMITED
PROFILE                        RESOURCE_NAME                    RESOURCE LIMIT
------------------------------ -------------------------------- -------- ----------------------------------------
DEFAULT                        PASSWORD_LOCK_TIME               PASSWORD .0006
DEFAULT                        IDLE_TIME                        KERNEL   UNLIMITED
DEFAULT                        PASSWORD_GRACE_TIME              PASSWORD 10
DEFAULT                        CONNECT_TIME                     KERNEL   UNLIMITED
DEFAULT                        PRIVATE_SGA                      KERNEL   UNLIMITED
16 rows selected.

--当设置简单密码时报出相应的设置

SQL> alter user test identified by sdf;
alter user test identified by sdf
*
ERROR at line 1:
ORA-28003: password verification for the specified password failed
ORA-20002: Password length less than 4

--当设置复杂密码时设置成功

SQL> alter user test identified by "s1A8?I";
User altered.

Precompiler HOLD_CURSOR and RELEASE_CURSOR Options [ID 2055810.6]

***Checked for relevance on 27-Jul-2012***



What are the Oracle Precompiler options HOLD_CURSOR and RELEASE_CURSOR  
and how do they affect the performance of a PCC program? 
 
First of all, these options apply to implicit and explicit cursors in 
all precompiled languages except Pro*Ada.  They apply ONLY to implicit 
cursors associated with INSERT, UPDATE, DELETE, or a single row SELECT 
in Pro*Ada.  An explicit cursor in a program is one explicitly created 
with EXEC SQL DECLARE C1 CURSOR FOR... 
 
This bulletin discusses what these options do internally and how changing  
them affects program performance.

HOLD_CURSOR is a precompiler command line parameter.

Summary Operation:
~~~~~~~~~~~~~~~~~~

	Statement submitted
	|
	Is it in an open cursor?--YES--> EXECUTE  <---.
	|NO                              ^   ^        |
	Is HOLD_CURSOR=Y &               |   |        |
	stmt in HC 'cache'?-----YES------'   |        |
	|NO                                  |        |
	Hash it + compare with sql area      |        |
	|                                    |        |
	is it in sql area -----YES----(Soft Parse)    |
	|NO                                           |
	--------------(Hard Parse)--------------------'
	

NB:     Both the soft and hard parse register as a parse in tkprof.
        If the cursor is open and it is not in the SQL_AREA then it clearly
        has to parse it (not shown in the diagram!)


The HOLD_CURSOR and RELEASE_CURSOR Options 
------------------------------------------  
  
What are the Oracle Precompiler options HOLD_CURSOR and RELEASE_CURSOR 
and how do they affect the performance of a PCC program? 
 
First of all, these options apply to implicit and explicit cursors in 
all precompiled languages except Pro*Ada.  They apply ONLY to implicit 
cursors associated with INSERT, UPDATE, DELETE, or a single row SELECT 
in Pro*Ada.  An explicit cursor in a program is one explicitly created  
with EXEC SQL DECLARE C1 CURSOR FOR... 
 
Following will be a discussion of what these options do internally and 
how changing them affects program performance. 
 
What exactly do we mean by CURSOR?  Unfortunately, we mean two differ- 
ent things: 
 
    1.  The program cursor - A data structure associated with a SQL 
        statement.  
 
        A program cursor is declared for each SQL statement that the 
        precompiler finds in your program.  For the statements 
  
        EXEC SQL DECLARE SEL_EMP_CURS CURSOR FOR... 
        EXEC SQL INSERT...  
 
        PCC will declare two program cursors, say c1 and c2. 
 
    2.  The Oracle cursor (also called the context area) - The work 
        area created dynamically at run time; this area contains the 
        parsed statement, the addresses of the host variables, and 
        other information necessary to execute the SQL statement.  
 
These two cursors are linked together via the cursor cache.  The ini- 
tial size of the cursor cache is determined by the MAXOPENCURSORS op- 
tion.  
 
The following diagram illustrates the relationship described above af- 
ter an insert and an update have been executed in your program: 
  
                                  CURSOR CACHE 
                               +-----------------+  
EXEC SQL INSERT...             |   Cache entry   |            Oracle  
Program cursor P(1)   <---->   |      C(1)       |   <---->   cursor 
                               +-----------------+  
EXEC SQL UPDATE...             |   Cache entry   |            Oracle 
Program cursor P(2)   <---->   |      C(2)       |   <---->   cursor 
                               +-----------------+ 
    .                          .                 .  
    .                          .                 . 
                               +-----------------+ 
EXEC SQL DELETE...             |   Cache entry   | 
Pgm cursor P(MAXOPENCURSORS)   |P(MAXOPENCURSORS)| 
                               +-----------------+  
EXEC SQL SELECT...  
Pgm cursor P(MAXOPENCURSORS+1) 
  
etc...  
 
 
How are the HOLD_CURSOR and RELEASE_CURSOR options related to this 
view? 
 
The HOLD_CURSOR option deals with the link between the program cursor 
and its cache entry. 
 
The RELEASE_CURSOR option deals with the link between the Oracle cur- 
sor and the cache entry. 
 
For SQL statements that are FREQUENTLY RE-EXECUTED, the bottom line is 
this:  if you want to maximize performance, make sure these SQL state- 
ments stay "glued" to their respective Oracle cursor. 
 
What does it mean when a SQL statement is "glued" to its Oracle cur- 
sor?  It means that both links between the SQL statement and its Ora- 
cle cursor are made permanent. 
 
Why would you want to keep a statement "glued" to its context area? 
Because the context area contains the parsed statement and other in- 
formation necessary to execute the statement, such as the addresses of 
the host variables.  Maintaining access to this information makes sub- 
sequent execution of the statement much faster. 
 
How do you "glue" a statement to a cache entry?  By correct use of the 
HOLD_CURSOR and RELEASE_CURSOR options via the PCC command line or in- 
line with EXEC ORACLE OPTION(...).  
 
For instance, with HOLD_CURSOR=YES as the Oracle option, a cache entry 
cannot be flagged for reuse.  This has important implications.  If all 
cache entries have been used up and a new cache entry is needed for a 
new SQL statement such that the number of cache entries would now ex- 
ceed the number specified in MAXOPENCURSORS, Oracle will use the first 
cache entry marked reuseable. 
  
For example, in the above diagram, if the cache entry C(1) is marked 
reusable, and the program is about to execute the EXEC SQL SELECT...  
(program cursor P(MAXOPENCURSORS+1),  and the number of cache entries 
in use already equals MAXOPENCURSORS, cache entry C(1) and its Oracle  
cursor will now be linked to the select statement.  A subsequent exe- 
cution of the insert statement would require pre-empting a cache entry 
and its Oracle cursor from another SQL statement and performing a re- 
parse. 
 
Correspondingly, with the default RELEASE_CURSOR=NO as the Oracle op- 
tion, the link between the cache entry and the Oracle cursor (the con- 
text area) is maintained after the statement is executed so that the 
parsed statement and, more importantly, the allocated memory stay 
available. 
 
The freeing up of this memory by RELEASE_CURSOR=YES means that the 
next statement that gets linked to this cache entry will require an 
expensive reallocation of memory in addition to a reparse.  Ugh!  Why 
would anybody want RELEASE_CURSOR=YES?  We will see later on. 
 
 Program cursor - - - - - [ Cursor cache entry ] - - - - -  Oracle  
for SQL statement                                           cursor  
                    ^                                ^  
            HOLD_CURSOR=YES                   RELEASE_CURSOR=NO 
      program cursor is permanently       cache entry maintains the 
        linked to its cache entry.       address of its context area. 
 
So the HOLD_CURSOR option is intimately tied to the MAXOPENCURSORS op- 
tion.  What exactly is the MAXOPENCURSORS option?  First of all, MAX- 
OPENCURSORS is a misnomer.  It should more appropriately be called 
INITIAL_CURSOR_CACHE_SIZE.  (Okay, so it's a mouthful.)  Anyway, if  
all cursor cache entries are currently marked "not reusable" either  
because of the HOLD_CURSOR option or because the associated statement 
is currently being executed (an explicitly opened cursor is still be- 
ing fetched on and hasn't been closed yet), then a request for a new 
cursor will actually result in the extension of the cursor cache at 
runtime (i.e. if MAXOPENCURSORS=10, and all 10 entries are active, 
then an 11th will be created).  Just letting the precompiler reuse the 
oldest cache entry won't always work, as the following example illus- 
trates:  Imagine the case where the user has ten explicitly declared 
cursors opened, and wants to execute an eleventh.  If the program ac- 
tually reuses the oldest program cursor, the user would lose his cur- 
rent position in the first cursor and would not be able to fetch from 
it anymore.       
 
By the way, if an eleventh cache entry is created, when that cursor is 
closed the eleventh entry is not removed.  Setting MAXOPENCURSORS low 
saves memory, but causes potentially expensive dynamic allocations of 
new cache entries if they're needed.  Setting it high assures quick  
execution, but may use more memory than necessary.  
 
What if a statement is not executed repeatedly in a program?  Then you 
could go with the other options HOLD_CURSOR=NO and RELEASE_CURSOR=YES. 
With the HOLD_CURSOR=NO option, the link between a program cursor and 
its cache entry is not permanent.  The cache entry is automatically 
marked reusable in case it is needed.  With the RELEASE_CURSOR=YES op- 
tion, the Oracle cursor (the context area) is automatically freed and 
the parsed statement lost.  A reason you might use this option is if 
you are limited by the number of Oracle cursors (MAXOPENCURSORS) at 
your site due to memory issues.  You may want to incur the cost of re- 
allocating memory and reparsing in order to manage memory more effec- 
tively. 
  
An advantage of setting RELEASE_CURSOR=YES is that until the link be- 
tween the cache entry and the Oracle cursor (context area) is removed, 
ORACLE keeps parse locks on any tables referenced in the SQL state- 
ment.  These parse locks prevent other users and you from ALTERing or 
DROPping the tables (does ORA-0057 sound familiar?).  Also, in Version 
5, it will free up the read-consistent image of the referenced tables 
stored in ORACLE's Before Image file. 
 
What do we mean when we say that RELEASE_CURSOR=YES takes precedence 
over HOLD_CURSOR=YES?  With RELEASE_CURSOR=YES, the link between the 
Oracle cursor and the cache entry is cut and the Oracle cursor is 
freed (closed), so even if your program cursor is permanently linked 
to the cache entry because HOLD_CURSOR=YES, you will still have to re- 
allocate memory and reparse the statement.  So subsequent executions 
of a statement don't benefit from the HOLD_CURSOR=YES option because 
RELEASE_CURSOR=YES. 
 
For programmers experienced with OCI, here's the OCI equivalent of 
what's happening: 
 
#define MAXOPENCURSORS 5 
 
char     *sql_stmts[10];  
curs_def cursor[MAXOPENCURSORS]; 
 
oopen(cursor[0],...); 
osql3(cursor[0],...,sql_stmts[0],...);  
 
An example of a "cache entry" being linked to another SQL statement 
later on in the program is as follows: 
 
osql3(cursor[0],...,sql_stmts[5],...);  
 
I am forced to reuse one of my "cache entries" to execute the sixth 
SQL statement. 
 
An example of a context area being freed is:  
                 
oclose(cursor[0]);      
 
Reusing cursor[0] would require another oopen() and another osql3()-- 
another dynamic allocation of memory and another reparse. 
 
 
Conclusion 
---------- 
 
As a programmer, you will get the most from these options by using 
them selectively inline rather than specifying them as options at pre- 
compile time.

Reference:

Pro*C/C++ Precompiler Programmer's Guide

SQL Parsing Flow Diagram [ID 32895.1]

PURPOSE
~~~~~~~
The document gives a overview of Parsing. 
 
SCOPE & APPLICATION
~~~~~~~~~~~~~~~~~~~
For users requiring a general overview of how parsing works.


Introduction
============

This article show the parsing mechanism as a flow diagram. 
Its main purpose is to show the difference between a 'soft' and a
'hard' parse.

It is intended to give a feel of how parsing operates to make 
explanation of parsing activity easier.


SQL Parsing Flow Diagram
========================

 Statement 
 Submitted
 |
 Is it in an open cursor?--------------YES----V   
 |                                            |  
 NO                                           |   
 |                                            |
 Is SESSION_CACHED_CURSORS = Value            |  
 and cursor in Server Side ------------YES----V   In these 3 cases we  
 Session Cursor cache?                        |   know that the cursor has 
 |                                            |   already been parsed, so 
 NO                                           |   re-parsing is
 |                                            |   unnecessary.
 Is HOLD_CURSOR=Y                             |
 and cursor in           --------------YES----V      
 Held cursor cache?                           |       
 |                                            |       
 NO                                           |        
 |                                            |              ^
 OPEN A CURSOR                                |  CLIENT SIDE |       
 |                                            | -------------|
 Statement is Hashed and compared             |  SERVER SIDE | 
 with the Hashed value in the sql area        |              V
 |                                            V
 Is it in sql area? --YES-(Soft Parse)--> ---------
 |                                       |         |
 NO                                      | EXECUTE |
 |                                       |         |
 PARSE STATEMENT ('Hard' Parse)---------> ---------
 

NOTES
=====

1. A cursor is an address on the client that points to the memory  
   location of a SQL statement on the server.
   Multiple-client cursors may point at the same address on the server.

2. Remember that 'Client' and 'Server' sides may reside on the same 
   machine - in which case Client/Server is a logical distinction.

3. If a cursor is open, then the statement will be in the sql_area, 
   so no parsing is necessary.

   This is why locks may remain when a client is terminated
   abnormally (such as a PC Client being turned off without
   closing open cursors).

4. SESSION_CACHED_CURSORS is the initialisation parameter that
   specifies how many cursors to hold open for a particular session.
   The open cursor request will still be sent to the server but it will 
   not be executed once a matching cursor is found in the session cursor cache.

5. HOLD_CURSOR is an precompiler parameter that specifies that an 
   individual cursor should be held open.

   See Page 11-3 of the Programmer's guide to the Oracle Precompilers.

6. Both the soft and hard parse register as a parse in tkprof. Hashing the
   current statement updates the parse count.

7. Soft parse avoids many of the steps taken during the parse phase for a 
   particular statement. Initial syntactic and semantic checks are made and 
   then the statement is hashed and compared with hashed statements in 
   the SQL area. If a match is found, then existing information is used
   and relatively expensive steps (such as query optimization etc.) are avoided.

8. The 10053 event is only invoked during a hard parse.


Additional Search Words
~~~~~~~~~~~~~~~~~~~~~~~

HARD; HOLD_CURSOR; PARSE; SESSION_CACHED_CURSORS; SOFT; SQL; 
----------------------------------------------------------------

Library Cache内部机制详解

转载自:http://www.hellodb.net/2010/07/oracle-library-cache.html

Library cache是Shared pool的一部分,它几乎是Oracle内存结构中最复杂的一部分,主要存放shared curosr(SQL)和PLSQL对象(function,procedure,trigger)的信息,以及这些对象所依赖的table,index,view等对象的信息。

Library cache需要解决三个问题:

1.快速定位的问题:Library cache中对象众多,Oracle如何管理这些对象,以便服务进程可以迅速找到他们需要的信息。比如某个服务进程需要迅速定位某个SQL是否存在于Library cache中。

2.关系依赖的问题:Library cache中的对象存在复杂的依赖关系,当某个objec失效时,可以迅速将依赖其的对象也置为失效状态。比如某个表发生了结构变化,依赖其的SQL语句需要重新解析。

3.并发控制的问题:Library cache中必须有一个并发控制的机构,比如锁机制,来管理大量共享对象的并发访问和修改的问题,比如某个SQL在重新编译的同时,其所依赖的对象不能被修改。

Library cache结构:

Oracle利用hash table结构来解决library cache中快速定位的问题,hash table就是很多hash bucket组成的数组:

image

原理与buffer cache中定位block的方式相同,将对象信息(比如SQL)hash定位到某个hash bucket中,然后顺序扫描bucket中的 List,实现快速定位对象的目的。

Library cache handle是对象的一个指针,其中的namespace属性表示其指向的对象的类型:比如CRSR(Cursor),TABL(Table),INDX(Index) ,PROD(Procedure),TRIG(Trigger)等等。

LCO(Library cache object)是handel指向的对象,包含了以下几个部分的内容:

1.dependency table:

指向本对象所依赖的对象,比如:select * from emp这个cursor的对象,依赖emp这个表,这里指向了emp这个表的handle。

2.child table:

指向本对象的子对象,比如某个游标的子游标。子游标是指SQL文本相同,但是SQL的实际含义不同的情况,比如执行的用户不同,执行计划不同,执行的环境不同等等,我们一般称之为SQL的不同版本。一个SQL至少包含一个父游标和一个子游标。

3.authorization table:

对象的授权信息。

4.type

Library cache object的type,包括:shared cursor,index,table,cluster,view,synonym,sequence,procedure,function,package,table body,package body,trigger等等。

5.data blocks

data block是一个指针,指向了data heap,即存放真实数据的地方,主要包括:diana tree, p-code, source code, shared cursor context area等等,如下图:

image

Library cache对象依赖关系:

对象依赖关系是利用LCO中的dependency table来完成的,我们设想以下的情况,用来说明对象间的依赖关系:

两个共享游标:

SQL1: select * from emp;

SQL2: select * from emp和select a.name from emp a,dept b where a.dept_id=b.id and b.name=:1;

image

SQL1产生了两个子游标,也就是SQL文本相同的两个不同版本,他们同时依赖emp表。SQL2只有一个版本,因为每个游标最少有一个子游标,所以它只有一个子游标,并且同时依赖dept表和emp表。

Library cache中的并发控制

Oracle利用Library cache lock和Library cache pin来实现并发控制,Library cache lock是在handle上获取的,而Library cache pin则是在data heap上获取。访问对象时,首先必须获取handle上的lock,然后将访问的数据pin在内存中。lock的作用是控制进程间的并发访问,而pin的作用是保证数据一致性,防止数据在访问时被交换出去。

Library cache lock有三种模式:null,share,exclusive,Library cache pin有两种模式:share,exclusive。下面详细解释在修改和访问对象时,lock和pin的作用:

修改对象

编译SQL或PLSQL对象,获取该对象(cursor,procedure)handle上exclusive类型的lock,并且持有data heap上exclusive类型的pin,防止其他人读取和修改。同时,在该对象所依赖的对象(table)上,必须持有一个share类型的lock和pin,防止在修改的过程中,被其他进程所修改。

访问对象

访问SQL或PLSQL对象,获取该对象(cursor,procedure)handle上NULL类型的lock,并且持有data heap上share类型的pin,同时,在其依赖的对象(table)上持有share类型的lock和pin。如果一个procedure依赖另外一个function,那么在被依赖的function上,也需要持有share类型的lock和pin。

NULL类型的lock比较特殊,它只存在于cursor和procedure等只读对象上,它并不起到任何并发控制的作用,它更象是一个trigger,当对象失效时,通知所有访问这个cursor的进程。比如:select * from emp这个SQL,依赖emp表,当emp表发生变化时,cursor上的NULL lock被打破,所有有访问这个cursor的进程都会知道该对象已经失效。

当持有对象的library cache pin时,会在row cache中对相应的对象加锁,就是row cache lock,阻止可能导致数据字典信息混乱的DDL发生。

image

lock和pin的实现类似于enqueue,在每个handle上都有lock和pin的holder list和waiter list,用来保存持有该资源和等待该资源的队列。

阻塞分析

现实情况中,我们有一个数据库中存在被应用大量频繁访问的procedure,当依赖的表发生变更时,导致该procedure失效,这时会出现大量的library cache lock和library cache pin的等待,堵塞应用访问,造成了重大故障。出现这个问题的原因是:当procedure失效后,所有访问该对象的进程都尝试去编译,大量进程尝试获取exclusive类型的lock和pin,出现了大量的等待。后续的Oracle版本作出了改进,当出现这种情况时,只允许第一个进程尝试去编译该对象,编译通过后,所有的进程就可以并发访问,避免了大量进程同时尝试编译的情况出现。

Library cache中的Latch:

Library cache中相关的latch包括:shared pool latch,library cahce latch,library cache lock latch,library cache pin latch。

Share pool latch的主要作用是分配或释放空间时使用,从Oracle9i开始,sharedpool被分成了很多个subpool,由多个shared pool latch保护,Oracle开始支持更大的shared pool。

Library cache latch的主要作用是在hash bucket中定位handle时使用,library cache lock latch和library cache pin latch分别是获取lock和pin时,需要取得的latch。

shared pool大小不合理,大量的硬解析以及SQL版本过多都可能导致shared pool latch和library cache latch的争用。

从Oracle10g开始,Oracle正在逐步用mutex取代library cache中的latch,cursor:pin S和cursor:pin X相当于share和exclusive类型的library cache pin,cursor:pin S wait on X则表示share方式正在等待exclusive锁定。

Dump LIBRARY_CACHE的使用与分析

Dump LIBRARY_CACHE方法:

方法A – 使用ORADEBUG:

SQL> oradebug setmypid
Statement processed.
SQL> oradebug unlimit
Statement processed.
SQL> oradebug dump library_cache 8
Statement processed.
SQL> oradebug tracefile_name
/u01/app/oracle/admin/fs10g/udump/fs10g_ora_14100.trc

方法B – 使用EVENT:

SQL> alter session set events 'immediate trace name library_cache level 8';

Session altered.

DUMP LEVEL说明:

=====
  9.2.0
  =====
   Typically LEVEL 11 is used but actual levels are now a bitmask:
    Level = 1   Dump library cache statistics
    Level = 2   Dump hash table summary
    Level = 4   Dump library cache objects with basic information
    Level = 8   Dump objects with detailed information 
                        (including child references, pin waiters etc..)
    Level = 16  Dump heap sizes (can be latch intensive)
    Level = 32  Dump heap information 
    So level 11 = 8 + 2 + 1 above
    
    Level > 100
      Dumps the library cache object with HANDLE = LEVEL  with medium detail

    Level > 1000000000 
      Dumps the library cache object with HANDLE = LEVEL - 1000000000
      with full detail
      
  =====
  7.0 - 9.0.1
  =====
   Typically LEVEL 10 is used but the actual levels are as below.
   NOTE: These are absolute values and NOT a bitmask.
    Level = 1   Dump Library Cache Statistics only
    Level = 2   Dump statistics and Hash Table summary
    Level = 3   Dump all above plus library cache objects in summary form
    Level > 4   Dump all above plus library cache objects in detail
                        (including child references, pin waiters etc..)

    Level > 100
      Dumps the library cache object with HANDLE = LEVEL  with medium detail

    Level > 1000000000 
      Dumps the library cache object with HANDLE = LEVEL - 1000000000
      with full detail

DUMP出的trace分析如下:

BUCKET 167: -- Bucket编号
  LIBRARY OBJECT HANDLE: handle=75ad0f60 mutex=0x75ad1090(0) 
  -- handle: Memory address of the object handle
  name=SYS.HISTGRM$ 
  --name: Name of the library cache object
  hash=5766cfd02bed79cf647408ed758000a7 timestamp=11-18-2012 00:13:50 
  -- hash: Value that this object hashed to
  -- timestamp: Timestamp of the object’s last modification
  namespace=TABL flags=PKP/KGHP/TIM/KEP/SML/BSO/[02900002]
  -- namespace: CRSR: cursor, TABL/PRCD/TYPE: table/procedure/type,BODY/TYBD: package body/type body, TRIG: trigger, INDX: index, CLST: cluster, OBJE: object, PIPE: pipe, LOB: lob, DIR: directory, QUEU: queue,OBJG: replication object group, PROP: replication propagator, JVSC: Java source, JVRE: Java resource, ROBJ: server-side RepAPI, REIP: replication internal package, CPOB: context policy object, EVNT: pub_sub internal information, SUMM: summary, DIMN: dimension, CTX: application context, OUTL: stored outline, RULS: ruleset object, RMGR: resource manager, IFSD: IFS data, PPLN: pending scheduler plan, PCLS: pending scheduler class, SUBS: subscription information, LOCS: location information, RMOB: remote objects information, RSMD: RepAPI snapshot metadata, JVSD: Java shared data.
  -- flags: RON: read only, REM: remote object, FIX: fixed object, CGA: object in CGA memory, TIM: valid timestamp, PTM: has logged a previous timestamp, PKP: permanently kept object, OBS: has been marked obsolete, KEP: is marked to be kept in the shared pool, FUL/FUP: object should be freed upon unlock or unpin, USE: in use (do not unpin), PN0: heap 0 should be kept pinned as long as any user has a lock on the handle, SML/MED/LRG: small/medium/large indicates size of the handle, SEC: this object is secondary.
  kkkk-dddd-llll=0101-0141-0741 lock=0 pin=0 latch#=1 hpc=0018 hlc=0018
  -- lock: Current lock mode (0: no lock, N: Null, S: Share, X: Exclusive)
  -- pin: Current pin mode (0: no lock, S: Share, X: Exclusive)
  -- latch: Associated child latch id
  lwt=0x75ad1008[0x75ad1008,0x75ad1008] ltm=0x75ad1018[0x75ad1018,0x75ad1018]
  -- lwt: Lock waiters linked list
  -- ltm: Temporary locks linked list. Broken locks and locks that are in the middle of being processed are in the temporary list.
  pwt=0x75ad0fd0[0x75ad0fd0,0x75ad0fd0] ptm=0x75ad0fe0[0x75ad0fe0,0x75ad0fe0]
  -- pwt: Pin waiters linked list
  -- ptm: Temporary pins linked list. Pins that are in the middle of being processed are in the temporary list.
  ref=0x75ad1038[0x75ad1038,0x75ad1038] lnd=0x75ad1050[0x759c0518,0x75ad1968]
  -- ref: Reference list. This is a list of handles that are referenced by this objects. Each reference has a flag determining whether they are a dependency, a child, a read-only dependency, and so on.
    LIBRARY OBJECT: object=7235e208
    -- object: memory address of object structure
    type=TABL flags=EXS/LOC[0005] pflags=[0000] status=VALD load=0
    -- type: type of object, CRSR: cursor, INDX: index, TABL: table, CLST: cluster, VIEW: view, SYNM: synonym, SQNC: sequence, PRCD: procedure, BODY: package body, FNCT: function, PCKG: package, NEXS: nonexistent object, PKBD: package body, TRIG: trigger, TYPE: type, TYBD: type body, OBJE: object, USER: user, LINK: database link, PIPE: pipe, TABP: table partition, INDP: index partition, LOB: lob, LIBR: library, DIR: directory QUEU: queue, IOT: index organized table, OBJG: replication object group, PROP: replication propagator, JVSC: Java source, JVCL: Java class, JVRE: Java resource, JVJA: Java jar, ITYP: index type for extensible indexing, OPR: operator, TASP: table subpartition, INSP: index subpartition, ROBJ: reserved for server-side RepAPI, REIP: replication internal package, CPOB: context policy object, 
    -- flags: Flags, EXS/NEX: exists/nonexistent, LOC: locally represented, BOW: bad owner or database link, REA: read only object, NRC: no recovery required (pipes), CRT/ALT/DRP/UPD: object being created/altered/dropped/updated, PRG: marked to be purged, MEM: object has frame memory associated with heap 0, REA: object has been protected with read-only access at least once, NOA: object has been protected with no access at least once EVNT: pub_sub internal information, LBP: lob partition, LBSP: lob subpartition, SUMM: summary, DIMN: dimension, CTX: application context, OUTL: stored outline, RULS: ruleset object, SPLN: sheduler plan, SCLS: scheduler class, PPLN: pending scheduler plan, PCLS: pending scheduler class, SUBS: subscription information, LOCS: location information, RMOB: remote object, RSMD: RepAPI snapshot metadata, IFSD: IFS data, JVSD: Java share data
    -- pflags: Public flags, NST: object has no persistent state, DBG PL/SQL: object with debug data, SIM: simple PL/SQL block, SWR: shrink-wrapped PL/SQL item, REU: MTS-reusable PL/SQL object, ITS: inconsistently time-stamped STANDARD, HOC: heterogeneous option callout, PRP: potential REF-dependency parent, BCM: object is being compiled, IVR: invoker’s rights, REP: repeatable, MTR: Mark TO8 trusted procedure, package, function
    -- status: Status, VALD: valid/authorized without errors, AERR: valid/authorized with authorization errors, CERR: valid/authorized with compilation errors, UNAU: valid/unauthorized, INVL: invalid/unauthorized, KPTS: invalid/unauthorized but keep the timestamp
    -- load: Current load lock mode (0: no lock, X:Exclusive if object is being locked)
    CHILDREN: size=16
    -- Child table dump follows. The initial size of this table has room for 16 children. If more are required, then the child table is extended in chunks of 16. For performance reasons, it is better not to have more than 16 versions of the same cursor.
    child#    table reference   handle
    ------ -------- --------- --------
         0 72037970  720375e0 75942fd8
    -- child#: Child number
    -- table: Child table address
    -- reference: Reference address (corresponds to the references linked list)
    -- handle: Handle address of child object
    DATA BLOCKS:
    -- DATA BLOCKS: Heap descriptors follow
    data#     heap  pointer    status pins change whr
    ----- -------- -------- --------- ---- ------ ---
        0 75ad0ea0 7235e360 I/P/A/-/-    0 NONE   00 
        8 7235e508 7235df98 I/P/A/-/-    0 NONE   00 
        9 72141b90        0 I/-/-/-/-    0 NONE   0c 
       10 72141ac8        0 I/-/-/-/-    0 NONE   0c 
    -- data#: Number of memory heap
    -- heap: Heap descriptor (memory address)
    -- pointer: Data pointer
    -- status: Status (I: initialized, P: pinned, A: allocated)
    -- pins: Data heap pin count
    -- change: Data heap change (NONE, INSERT, UPDATE, DELETE)
  BUCKET 167 total object count=1

DBMS_SYSTEM包

DBMS_SYSTEM包是一个非常有用的包, 其中包括设置SQL_TRACE, 设置EVENT, 打印指定的TRACE信息等。

1. DBMS_SYSTEM.KSDWRT – 设置打印指定的信息到TRACE

PROCEDURE KSDWRT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 DEST                           BINARY_INTEGER          IN
 TST                            VARCHAR2                IN

DEST:输出的目标位置

  • 1 – Write to trace file.
  • 2 – Write to alertlog.
  • 3 – Write to both.

TST:输出的文本信息

示例:

SQL> exec dbms_system.ksdwrt(2, 'this is a test');

PL/SQL procedure successfully completed.

-- alert日志

Thu Feb  7 22:15:52 2013
this is a test

2. DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION – 对其他SESSION设置SQL_TRACE

PROCEDURE SET_SQL_TRACE_IN_SESSION
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SID                            NUMBER                  IN
 SERIAL#                        NUMBER                  IN
 SQL_TRACE                      BOOLEAN                 IN

示例:

-- Session(159,3)
SQL-159,3> exec dbms_system.set_sql_trace_in_session(137,41,true)

PL/SQL procedure successfully completed.

-- Session(137,41)
SQL-137,41> select count(*) from stl.stl;

  COUNT(*)
----------
   2622208

SQL-137,41> !cat $ORACLE_BASE/admin/fs10g/udump/*10246*.trc

/u01/app/oracle/admin/fs10g/udump/fs10g_ora_10246.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1
System name:    Linux
Node name:      db.oracle.com
Release:        2.6.32-300.10.1.el5uek
Version:        #1 SMP Wed Feb 22 17:37:40 EST 2012
Machine:        x86_64
Instance name: fs10g
Redo thread mounted by this instance: 1
Oracle process number: 14
Unix process pid: 10246, image: oracle@db.oracle.com (TNS V1-V3)

*** 2013-02-07 22:21:58.007
*** SERVICE NAME:(SYS$USERS) 2013-02-07 22:21:58.006
*** SESSION ID:(137.41) 2013-02-07 22:21:58.006
=====================
PARSING IN CURSOR #4 len=28 dep=0 uid=0 oct=3 lid=0 tim=1328366130915156 hv=3955824146 ad='6c86e6d8'
select count(*) from stl.stl
END OF STMT
PARSE #4:c=55991,e=54759,p=0,cr=183,cu=0,mis=1,r=0,dep=0,og=1,tim=1328366130915151
EXEC #4:c=0,e=35,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1328366130915234
FETCH #4:c=842872,e=824554,p=61854,cr=63153,cu=0,mis=0,r=1,dep=0,og=1,tim=1328366131739838
FETCH #4:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=1328366131740235
=====================
PARSING IN CURSOR #2 len=52 dep=0 uid=0 oct=47 lid=0 tim=1328366131740672 hv=1029988163 ad='75aacfd0'
BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
END OF STMT
PARSE #2:c=0,e=35,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1328366131740667
EXEC #2:c=0,e=158,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=1328366131740890
STAT #4 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=63153 pr=61854 pw=0 time=824541 us)'
STAT #4 id=2 cnt=2622208 pid=1 pos=1 obj=11854 op='TABLE ACCESS FULL STL (cr=63153 pr=61854 pw=0 time=18567695 us)'

-- Session(159,3)
SQL-159,3> exec dbms_system.set_sql_trace_in_session(137,41,false)

PL/SQL procedure successfully completed.

3. DBMS_SYSTEM.SET_EV / DBMS_SYSTEM.GET_EV  – 设置/获取Event

PROCEDURE SET_EV
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SI                             BINARY_INTEGER          IN
 SE                             BINARY_INTEGER          IN
 EV                             BINARY_INTEGER          IN
 LE                             BINARY_INTEGER          IN
 NM                             VARCHAR2                IN

SI:SID
SE: Serial#
EV: Event
LE: Level
NM: Username

实例:

-- Session(159,3)
SQL-159,3> exec dbms_system.set_ev(137,41, 10046, 12, '');

PL/SQL procedure successfully completed.

-- Session(137,41)
SQL-137,41> var v_event number
SQL-137,41> exec dbms_system.read_ev(10046, :v_event)

PL/SQL procedure successfully completed.

SQL-137,41> print v_event

   V_EVENT
----------
        12

SQL-137,41> select count(*) from stl.stl;

  COUNT(*)
----------
   2622208

SQL-137,41> 
SQL-137,41> !cat $ORACLE_BASE/admin/fs10g/udump/*10246*.trc
/u01/app/oracle/admin/fs10g/udump/fs10g_ora_10246.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1
System name:    Linux
Node name:      db.oracle.com
Release:        2.6.32-300.10.1.el5uek
Version:        #1 SMP Wed Feb 22 17:37:40 EST 2012
Machine:        x86_64
Instance name: fs10g
Redo thread mounted by this instance: 1
Oracle process number: 14
Unix process pid: 10246, image: oracle@db.oracle.com (TNS V1-V3)

*** 2013-02-07 22:21:58.007
*** SERVICE NAME:(SYS$USERS) 2013-02-07 22:21:58.006
*** SESSION ID:(137.41) 2013-02-07 22:21:58.006
=====================
PARSING IN CURSOR #4 len=28 dep=0 uid=0 oct=3 lid=0 tim=1328366897842470 hv=3955824146 ad='6c86e6d8'
select count(*) from stl.stl
END OF STMT
PARSE #4:c=1000,e=278,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1328366897842459
BINDS #4:
EXEC #4:c=0,e=96,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1328366897842644
WAIT #4: nam='SQL*Net message to client' ela= 7 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366897842706
WAIT #4: nam='db file scattered read' ela= 39 file#=5 block#=148 blocks=5 obj#=11854 tim=1328366897842963
WAIT #4: nam='db file scattered read' ela= 33 file#=5 block#=153 blocks=8 obj#=11854 tim=1328366897843205
WAIT #4: nam='db file scattered read' ela= 34 file#=5 block#=370 blocks=7 obj#=11854 tim=1328366897843648
WAIT #4: nam='db file scattered read' ela= 39 file#=5 block#=377 blocks=8 obj#=11854 tim=1328366897844102
.....
WAIT #4: nam='db file scattered read' ela= 20 file#=5 block#=63875 blocks=6 obj#=11854 tim=1328366898808029
FETCH #4:c=987850,e=965389,p=61911,cr=63153,cu=0,mis=0,r=1,dep=0,og=1,tim=1328366898808136
WAIT #4: nam='SQL*Net message from client' ela= 406 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898808628
FETCH #4:c=0,e=5,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=1328366898808676
WAIT #4: nam='SQL*Net message to client' ela= 4 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898808709
WAIT #4: nam='SQL*Net message from client' ela= 402 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898809138
=====================
PARSING IN CURSOR #2 len=52 dep=0 uid=0 oct=47 lid=0 tim=1328366898809305 hv=1029988163 ad='75aacfd0'
BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
END OF STMT
PARSE #2:c=0,e=69,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1328366898809280
BINDS #2:
kkscoacd
 Bind#0
  oacdty=123 mxl=4000(4000) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=1000000 frm=00 csi=00 siz=4000 off=0
  kxsbbbfp=7f46d409af80  bln=4000  avl=00  flg=15
 Bind#1
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=01 fl2=1000000 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7f46d41ccdc0  bln=22  avl=22  flg=05
  value=###
  An invalid number has been seen.Memory contents are :
Dump of memory from 0x00007F46D41CCDC0 to 0x00007F46D41CCDD6
7F46D41CCDC0 000010C1 00000000 00000000 00000000  [................]
7F46D41CCDD0 00000000 00000000                    [........]        
WAIT #2: nam='SQL*Net message to client' ela= 6 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898809769
EXEC #2:c=0,e=407,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=1328366898809816
WAIT #2: nam='SQL*Net message from client' ela= 252 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898810150
WAIT #0: nam='SQL*Net message to client' ela= 4 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898810248
WAIT #0: nam='SQL*Net message from client' ela= 152 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898810425
STAT #4 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=63153 pr=61911 pw=0 time=965346 us)'
STAT #4 id=2 cnt=2622208 pid=1 pos=1 obj=11854 op='TABLE ACCESS FULL STL (cr=63153 pr=61911 pw=0 time=18611393 us)'
WAIT #0: nam='SQL*Net message to client' ela= 4 driver id=1650815232 #bytes=1 p3=0 obj#=11854 tim=1328366898810813

最后是网上摘抄的DBMS_SYSTEM包的使用说明:

General
Source {ORACLE_HOME}/rdbms/admin/prvtutil.plb
First Available 7.3.4
Constants
Name Value

trace_file

1

alert_file

2

?

3
Dependencies SELECT name FROM dba_dependencies WHERE referenced_name = ‘DBMS_SYSTEM’

UNIONSELECT referenced_name FROM dba_dependencies WHERE name = ‘DBMS_SYSTEM’;

Security Model Execute is granted to OEM_MONITOR
ADD_PARAMETER_VALUE (new in 11g)

Writes a listed parameter to the spfile following a call to ALTER SYSTEM SET.

dbms_system.add_parameter_value(

parname IN VARCHAR2,value IN VARCHAR2,

scope IN VARCHAR2,

sid IN VARCHAR2,

position IN BINARY_INTEGER);

col value format a100SELECT value

FROM gv$parameter

WHERE name = ‘control_files’;

exec dbms_system.add_parameter_value(‘control_files’, ‘c: emp\control04.ctl’, ‘BOTH’, ‘orabase’, 4);

SELECT value

FROM gv$parameter

WHERE name = ‘control_files’;

DIST_TXN_SYNC
Distributed transaction synchronization used in XA interfaces. Not intended for end-user usage. dbms_system.dist_txn_sync(inst_num IN NUMBER);
exec dbms_system.dist_txn_sync(2);
GET_ENV

Returns the value of environment variables

dbms_system.get_env(var IN VARCHAR2, val OUT VARCHAR2);
set serveroutput onDECLARE

RetVal VARCHAR2(4000);

BEGIN

dbms_system.get_env(‘ORACLE_SID’, RetVal);

dbms_output.put_line(RetVal);

END;

/

DECLARE

RetVal VARCHAR2(100);

BEGIN

dbms_system.get_env(‘ORACLE_HOME’, RetVal);

dbms_output.put_line(RetVal);

END;

/

KCFRMS

Resets the timers displayed by MAX_WAIT in GV$SESSION_EVENT and MAXIORTM and MAXIOWTM in GV$FILESTAT (X$KCFIO)

dbms_system.kcfrms;
SELECT max_wait FROM gv_$session_event;SELECT maxiortm, maxiowtm FROM gv_$filestat;

exec dbms_system.kcfrms;

SELECT max_wait FROM gv_$session_event;

SELECT maxiortm, maxiowtm FROM gv_$filestat;

KSDDDT
Prints the date stamp to the target file (alert log and/or trace file) dbms_system.ksdddt;
exec dbms_system.ksdddt;
KSDFLS
Flushes any pending output to the target alert log or trace file dbms_system.ksdfls;
exec dbms_system.ksdfls;
KSDIND
Does an ‘indent’ before the next write (ksdwrt) by printing that many colons (:) before the next write. dbms_system.ksdind(lvl IN BINARY_INTEGER);Range of valid values from 0 to 30.
exec dbms_system.ksdind(5);exec dbms_system.ksdwrt(3, ‘Test Message’);
KSDWRT

Prints a message to the target file (alert log and/or trace file)

dbms_system.ksdwrt (dest IN BINARY_INTEGER, tst IN VARCHAR2);1: Write to the standard trace file

2: Write to the alert log

3: Write to both files at once

exec dbms_system.ksdwrt(3, ‘– Start Message –’);exec dbms_system.ksdwrt(3, ‘Test Message’);

exec dbms_system.ksdwrt(3, ‘– End Message –’);

READ_EV

Get the level for events set in the current sessionNOTE: We’ve received reports that READ_EV doesn’t work for event number 10046 in 11gR2 (11.2.0.3)

dbms_system.read_ev (iev IN BINARY_INTEGER, oev OUT BINARY_INTEGER);lev: event numbers 10000 to 10999

event level: default is 0 if not set

ALTER SYSTEM SET SQL_TRACE=TRUE;set serveroutput on

DECLARE

lev BINARY_INTEGER;

BEGIN

dbms_system.read_ev(10046, lev);

dbms_output.put_line(lev);

END;

/

REMOVE_PARAMETER_VALUE (new in 11g)

Removes a listed parameter to the spfile following a call to ALTER SYSTEM SET.Overload 1

dbms_system.remove_parameter_value(

parname IN VARCHAR2,value IN VARCHAR2,

scope IN VARCHAR2,

sid IN VARCHAR2);

TBD
Overload 2 dbms_system.remove_parameter_value(

parname IN VARCHAR2,position IN BINARY_INTEGER,

scope IN VARCHAR2,

sid IN VARCHAR2);

TBD
SET_BOOL_PARAM_IN_SESSION
Sets boolean-type init.ora parameters in any session dbms_system.set_bool_param_in_session(

sid IN NUMBER,serial# IN NUMBER,

parnam IN VARCHAR2,

bval IN BOOLEAN);

exec dbms_system.set_bool_param_in_session(10, 161, ‘sql_trace’, TRUE);
SET_EV

Set event trace level

dbms_system.set_ev(

si IN BINARY_INTEGER, — session idse IN BINARY_INTEGER, — session serial number

ev IN BINARY_INTEGER, — event number between 10000 and 10999

le IN BINARY_INTEGER, — event level

nm IN VARCHAR2);

Level Waits Binds
1 False False
4 False True
8 True False
12 True True
exec dbms_system.set_ev(10, 1008, 10046, 12, NULL);
SET_INT_PARAM_IN_SESSION

Sets integer-type init.ora parameters in any session

dbms_system.set_int_param_in_session(

sid IN NUMBER,serial# IN NUMBER,

parnam IN VARCHAR2,

intval IN BINARY_INTEGER);

exec dbms_system.set_int_param_in_session(10, 161, ‘sort_area_size’, 1048576);
SET_SQL_TRACE_IN_SESSION

Turn tracing on or off in any session

dbms_system.set_sql_trace_in_session(

sid NUMBER,serial# NUMBER,

sql_trace BOOLEAN);

exec dbms_system.set_sql_trace_in_session(10, 1008, TRUE);exec dbms_system.set_sql_trace_in_session(10, 1008, FALSE);
WAIT_FOR_EVENT

Puts the current session into a wait state for any named wait event

dbms_system.wait_for_event(

event VARCHAR2,extended_id BINARY_INTEGER,

timeout BINARY_INTEGER);

extended_id is placed into the P1 column of gv_$session_wait

exec dbms_system.wait_for_event(‘rdbms ipc message’, 50, 20);SELECT sid, event, p1, seconds_in_wait, state

FROM gv_$session_wait

WHERE sid = 10;

EVENT: 10500 turn on traces for SMON

10500事件可以为我们打开SMON后台进程的TRACE功能:

Error:  ORA 10500
Text:   turn on traces for SMON
-------------------------------------------------------------------------------
Cause:
Action:
        Level:  <=5  trace instance recovery
        > 5  trace posting of SMON
 
To set event 10500:

For the instance:
a.  Shutdown database
b.  Edit the initialisation parameter file and add:
    event="10500 trace name context forever, level <value>"
c.  restart the database

For the SMON session:
Post the SMON process using oradbx (Oracle 7) or oradebug (Oracle 8).
For oradebug from server manager issue:

oradebug setospid <OS PID>
oradebug event 10500 trace name context forever, level <value>

For further information about oradebug <Note:29786.1>
                              oradbx   <Note:28863.1>

<value> is 'Level' as per above

操作过程:

[ora10g@db ~]$ ps -ef | grep smon
ora10g    9053     1  0 14:59 ?        00:00:00 ora_smon_fs10g
ora10g    9104  3478  0 15:01 pts/0    00:00:00 grep smon
[ora10g@db ~]$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.1.0 - Production on Thu Feb 7 15:01:37 2013

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL> oradebug setospid 9053
Oracle pid: 8, Unix process pid: 9053, image: oracle@db.oracle.com (SMON)
SQL> oradebug event 10500 trace name context forever, level 10
Statement processed.

在bdump目录下会生成出相应的trc文件:

[ora10g@db bdump]$ ls
alert_fs10g.log  bdump_trc_20130207.tar  fs10g_arc0_9065.trc  fs10g_arc1_9067.trc  fs10g_lgwr_9049.trc  fs10g_smon_9053.trc
[ora10g@db bdump]$ cat fs10g_smon_9053.trc 
/u01/app/oracle/admin/fs10g/bdump/fs10g_smon_9053.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1
System name:    Linux
Node name:      db.oracle.com
Release:        2.6.32-300.10.1.el5uek
Version:        #1 SMP Wed Feb 22 17:37:40 EST 2012
Machine:        x86_64
Instance name: fs10g
Redo thread mounted by this instance: 1
Oracle process number: 8
Unix process pid: 9053, image: oracle@db.oracle.com (SMON)

*** 2013-02-07 15:01:54.397
*** SERVICE NAME:(SYS$BACKGROUND) 2013-02-07 15:01:54.397
*** SESSION ID:(164.1) 2013-02-07 15:01:54.396
Received ORADEBUG command 'event 10500 trace name context forever, level 10' from process Unix process pid: 9107, image: 
*** 2013-02-07 15:01:54.398
SMON: system monitor process posted
*** 2013-02-07 15:01:54.398
SMON: Posted too frequently, trans recovery disabled.

我们也可以通过”/proc/<OS PID>/fd”去查看具体文件的位置:

[ora10g@db bdump]$ ls -l /proc/9053/fd
total 0
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 0 -> /dev/null
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 1 -> /dev/null
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 10 -> /u01/app/oracle/admin/fs10g/adump/ora_9039.aud
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 11 -> /dev/zero
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 12 -> /dev/zero
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 13 -> /u01/app/oracle/product/10.2.0/db_1/rdbms/mesg/oraus.msb
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 14 -> /u01/app/oracle/product/10.2.0/db_1/dbs/hc_fs10g.dat
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 15 -> /u01/app/oracle/product/10.2.0/db_1/dbs/lkFS10G
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 16 -> /u01/app/oracle/oradata/fs10g/system01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 17 -> /u01/app/oracle/oradata/fs10g/undotbs01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 18 -> /u01/app/oracle/oradata/fs10g/sysaux01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 19 -> /u01/app/oracle/oradata/fs10g/users01.dbf
l-wx------ 1 ora10g oinstall 64 Feb  7 15:04 2 -> /u01/app/oracle/admin/fs10g/bdump/fs10g_smon_9053.trc
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 20 -> /u01/app/oracle/oradata/fs10g/stl_data01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 21 -> /u01/app/oracle/oradata/fs10g/stl_index01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 22 -> /u01/app/oracle/oradata/fs10g/stl_data_2k01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 23 -> /u01/app/oracle/oradata/fs10g/stl_data_32k01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 24 -> /u01/app/oracle/oradata/fs10g/test.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 25 -> /u01/app/oracle/oradata/fs10g/streams_tbs.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 26 -> /u01/app/oracle/oradata/fs10g/temp01.dbf
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 27 -> /u01/app/oracle/oradata/fs10g/temp02.dbf
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 28 -> /u01/app/oracle/product/10.2.0/db_1/rdbms/mesg/oraus.msb
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 3 -> /dev/null
lr-x------ 1 ora10g oinstall 64 Feb  7 15:04 4 -> /dev/null
l-wx------ 1 ora10g oinstall 64 Feb  7 15:04 5 -> /u01/app/oracle/admin/fs10g/udump/fs10g_ora_9039.trc
l-wx------ 1 ora10g oinstall 64 Feb  7 15:04 6 -> /u01/app/oracle/admin/fs10g/bdump/alert_fs10g.log
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 7 -> /u01/app/oracle/product/10.2.0/db_1/dbs/lkinstfs10g (deleted)
l-wx------ 1 ora10g oinstall 64 Feb  7 15:04 8 -> /u01/app/oracle/admin/fs10g/bdump/alert_fs10g.log
lrwx------ 1 ora10g oinstall 64 Feb  7 15:04 9 -> /u01/app/oracle/product/10.2.0/db_1/dbs/hc_fs10g.dat

EVENT: 10061 disable SMON from cleaning temp segment

Event-10061是一个Test的时间, 通过设置后可以禁用SMON清理临时段的动作。

[ora10g@db ~]$ oerr ora 10061
10061, 00000, "disable SMON from cleaning temp segment"
// *Cause:
// *Action:

如下是操作过程:

方法A(不需要重启数据库):

SQL> oradebug setospid 9172
Oracle pid: 8, Unix process pid: 9172, image: oracle@db.oracle.com (SMON)
SQL> oradebug event 10061 trace name context forever, level 10
Statement processed.

方法B(需要重启数据库):

SQL> select * from v$version
  2  ;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SQL> show parameter event

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
event                                string
SQL> alter system set event='10061 trace name context forever, level 10' scope=spfile;

System altered.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area  369098752 bytes
Fixed Size                  2020832 bytes
Variable Size             138414624 bytes
Database Buffers          222298112 bytes
Redo Buffers                6365184 bytes
Database mounted.
Database opened.
SQL> show parameter event

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
event                                string      10061 trace name context forev
                                                 er, level 10

设置完成了10061后, 我们通过中断一个online build的index去看一下, 是否生效:

-- Session(159,3) 
SQL-159,3> create index stl.idx_stl on stl.stl(object_id) online;

-- Session(140,1)
SQL-140,1> select owner, segment_name, EXTENT_ID,FILE_ID,BLOCK_ID, BLOCKS from dba_extents WHERE SEGMENT_TYPE='TEMPORARY';

OWNER                          SEGMENT_NAME                                                                       EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
------------------------------ --------------------------------------------------------------------------------- ---------- ---------- ---------- ----------
STL                            5.115                                                                                      0          5        113          8
STL                            5.115                                                                                      1          5        121          8
STL                            5.115                                                                                      2          5        129          8
STL                            5.115                                                                                      3          5        137          8
.....
STL                            5.115                                                                                     25          5      65161        128

26 rows selected.

SQL-140,1> alter system kill session '159,3';

System altered.

SQL-140,1> select owner, segment_name, EXTENT_ID,FILE_ID,BLOCK_ID, BLOCKS from dba_extents WHERE SEGMENT_TYPE='TEMPORARY';

OWNER                          SEGMENT_NAME                                                                       EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
------------------------------ --------------------------------------------------------------------------------- ---------- ---------- ---------- ----------
STL                            5.115                                                                                      0          5        113          8
STL                            5.115                                                                                      1          5        121          8
STL                            5.115                                                                                      2          5        129          8
STL                            5.115                                                                                      3          5        137          8
.....
STL                            5.115                                                                                     44          5      67593        128

45 rows selected.

我们可以看到在Session(159,3) 被Session(140,1) Kill后, create index stl.idx_stl on stl.stl(object_id) online所产生的临时段并没有被SMON回收。

ORA-1652: unable to extend temp segment by xxx in tablespace

由于表空间容量不足而导致的创建表/索引等段对象的时候经常会出现ORA-1652错误,但是提供的信息确实unable to extend temp segment by 1024 in tablespace。 这让很多的人感到不解。提示的表空间并不是存放temp segment的临时表空间,而是永久表空间。

其实在ORACLE进行空间分配的时候首先分配的空间是TEMPORARY SEGMENT在各项操作都完成的最后,在将这个TEMPORARY SEGMENT转变为PERMANENT SEGMENT。 知道了这个过程我们就可以理解为什么在空间不足时创建段为什么提示的是临时段表空间了, 因为最先分配的都是临时段空间,在之后才将其转换为永久段对象。通过如下的操作我们可以验证:

SQL> conn stl/sun
Connected.
SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
STL_32K                        TABLE
STL_2K                         TABLE
T1                             TABLE
T2                             TABLE
STL                            TABLE

SQL> select segment_name , bytes/1024/1024 from user_segments;

SEGMENT_NAME                                                                      BYTES/1024/1024
--------------------------------------------------------------------------------- ---------------
STL                                                                                           264
T2_IDX                                                                                        .25
T2                                                                                              2
T1                                                                                           .375
STL_2K                                                                                          2
STL_32K                                                                                         2

6 rows selected.

SQL> create table t as select * from stl;
create table t as select * from stl
                                *
ERROR at line 1:
ORA-01652: unable to extend temp segment by 1024 in tablespace STL_DATA

我们在一个空间不足的表空间中创建一张表,此时提示ORA-01652错误, 在创建表同时我们使用另一个会话查看临时段对象的信息:

SQL> select owner, segment_name, EXTENT_ID,FILE_ID,BLOCK_ID, BLOCKS from dba_extents WHERE SEGMENT_TYPE='TEMPORARY';

OWNER                          SEGMENT_NAME                                                                       EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
------------------------------ --------------------------------------------------------------------------------- ---------- ---------- ---------- ----------
STL                            5.99                                                                                       0          5         97          8
STL                            5.99                                                                                       1          5        105          8
STL                            5.99                                                                                       2          5        113          8
...
STL                            5.99                                                                                      98          5      61833       1024

OWNER                          SEGMENT_NAME                                                                       EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS
------------------------------ --------------------------------------------------------------------------------- ---------- ---------- ---------- ----------
STL                            5.99                                                                                      99          5      62857       1024

100 rows selected.

SQL> /

no rows selected

在创建表的同时,出现大量名为5.99的临时段的Extent, 在命令执行完成后这些Extent都不存在了。

具体的我们还可以模拟一个成功的案例,我们只有比较Temporary Segment和PERMANENT SEGMENT的BLOCKID等信息就可以知道。我在这里就不在演示了。

SQL_TRACE(10046)报告解读

SQL_TRACE或10046时间在进行SQL调优的时候经常会被使用, 它可以输出大量的SQL处理的内部信息。

报告内容分为三类:PARSING IN CURSOR部分, PARSE,EXEC,FETCH部分, STATS 部分

 

1. PARSING IN CURSOR部分:

例:

PARSING IN CURSOR #2 len=24 dep=0 uid=91 oct=3 lid=91 tim=12479594182 hv=574857817 ad='7ff3817f420' sqlid='3zjk3znj478kt'

解释:

len=24: sql长度

dep=0: 产生递归sql的深度

uid=91: user id

oct=3: oracle command type 命令的类型

lid=91: 私有的用户id

tim=12479594182: 时间戳

hv=574857817: sql的hash value

ad=’7ff3817f420: sql address

sqlid=’3zjk3znj478kt’: sql id

 

2. PARSE,EXEC,FETCH部分:

例:

PARSE #2:c=0,e=4298,p=0,cr=25,cu=0,mis=1,r=0,dep=0,og=1,plh=2229515557,tim=12479594181
EXEC #2:c=0,e=16,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=2229515557,tim=12479594262
FETCH #2:c=280802,e=3438229,p=33072,cr=33076,cu=0,mis=0,r=1,dep=0,og=1,plh=2229515557,tim=12483032552

解释:

c=280802: 消耗的CPU时间

e=3438229: elapsed time操作的用时, 单位:us – microsecond – 1000000th of a second

p=33072: physical reads 物理读的次数

cr=33076: consistent reads一致性读的数据块

cu=0: current方式读取的数据块

mis=0: currsor miss in cache 硬解析的次数

r=1: rows处理的行数

dep=0: depth 递归SQL的深度

og=1: optimizer goal优化器模式(1:all_rows, 2:first_rows, 3:rule)

plh=2229515557:  v$sql_plan.PLAN_HASH_VALUE

tim=12483032552: 时间戳

 

3. STATS 部分:

例:

STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='SORT AGGREGATE (cr=33076 pr=33072 pw=0 time=0 us)'
STAT #2 id=2 cnt=2319136 pid=1 pos=1 obj=74592 op='TABLE ACCESS FULL STL (cr=33076 pr=33072 pw=0 time=4684732 us cost=9138 size=0 card=2319136)'

解释:

id=2: 执行计划的行源号

cnt=2319136: 当前行源返回的行数

pid=1: 当前行源号的父号

pos=1: 执行计划中的位置

obj=74592: 当前操作的对象ID(如果当前行原始一个对象的话)

op=’TABLE ACCESS FULL STL (cr=33076 pr=33072 pw=0 time=4684732 us cost=9138 size=0 card=2319136: 当前行源的数据访问操作

 

无觅相关文章插件,快速提升流量