Oracle 11gR2에 새로 추가된 기능인 SCAN에 대해 간단히 정리합니다.. (까먹기 전에 --;)

Oracle은 새로운 버전이 나올때 마다 새로운 기능들을 추가하는데, 이번에 소개드릴 기능은 SCAN (Single Client Access Name) 입니다. 말 그대로 client에서 server를 접속할 때 여러개의 RAC 노드가 있더라도 하나의 access name을 갖도록 하는 기능입니다. 이 기능은 새로운 노드가 추가되거나 삭제되는 경우에도 적용되며, 사실 이것을 염두에 두고 있습니다. 

새로운 노드의 추가와 삭제와 상관없는 single client access name 이라..
딱 클라우드 컴퓨팅ㄱ이라는 단어가 생각나지 않습니다? 

아래의 tns alias 설정은 SCAN 기능을 사용할 경우 client의 tns alias 설정 sample 입니다. 
언듯보면.. 자세히 봐도 single DB 접속하는 tns alias와 동일합니다. 

TEST.ORACLE.COM =
(DESCRIPTION=
(ADDRESS=(PROTOCOL=tcp)(HOST=SCAN-TEST.ORACLE.COM)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=11GR2TEST.ORACLE.COM))
)

이전의 RAC에서의 tns alias는 아래와 같이 설정했었습니다. 

TEST.ORACLE.COM =
(DESCRIPTION=
(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=tcp)(HOST=TEST1-vip.ORACLE.COM)(PORT=1521))
(ADDRESS=(PROTOCOL=tcp)(HOST=TEST2-vip.ORACLE.COM)(PORT=1521))
)
(CONNECT_DATA=(SERVICE_NAME=11GR2TEST.ORACLE.COM))


그럼 어떻게 노드의 추가/삭제에도 동일한 access name을 가질 수 있을까요?
각 노드의 listener 앞에 새로운 listener를 두는 겁니다. 이 앞단의 listener들이 뒤의 RAC listener를 보게 됩니다.



11gR2 Grid Infrastructure Single Client Access Name (SCAN) Explained

SCAN Concepts

  • Single client access name (SCAN) is the virtual hostname to provide for all clients connecting to the cluster (as opposed to the vip hostnames in 10g and 11gR1).  
  • SCAN is a domain name registered to at least one and up to three IP addresses, either in the domain name service (DNS) or the Grid Naming Service (GNS).
  • By default, the name used as the SCAN is also the name of the cluster and must be globally unique throughout your enterprise. The default value for the SCAN is based on the local node name. SCAN name must be at least one character long and no more than 15 characters in length, must be alphanumeric - cannot begin with a numeral and may contain hyphens (-). If you require a SCAN that is longer than 15 characters, then select an Advanced installation.
  • For installation to succeed, the SCAN must resolve to at least one address.
  • SCAN VIP addresses must be on the same subnet as virtual IP addresses and public IP addresses.
  • Oracle strongly recommends that you do not configure SCAN VIP addresses in the hosts file. If you use the hosts file to resolve SCANs, then you will only be able to resolve to one IP address and you will have only one SCAN address - be sure to provide a hosts file entry for each SCAN address in hosts file in same order.
  • If hosts file is used to resolve SCAN hostname, you will receive Cluster Verification Utility failure at end of installation (see Note: 887471.1 for more details)
  • For high availability and scalability, Oracle recommends that you configure the SCAN to use DNS Round Robin resolution to three addresses.
  • Because the SCAN is associated with the cluster as a whole, rather than to a particular node, the SCAN makes it possible to add or remove nodes from the cluster without needing to reconfigure clients. It also adds location independence for the databases, so that client configuration does not have to depend on which nodes are running a particular database.
  • Clients can continue to access the cluster in the same way as with previous releases, but Oracle recommends that clients accessing the cluster use the SCAN. Clients using the SCAN can also access the cluster using EZCONNECT.
  • Grid Infrastructure will start local listener LISTENER on all nodes to listen on local VIP, and SCAN listener LISTENER_SCAN1 (up to three cluster wide) to listen on SCAN VIP(s); 11gR2 database by default will set local_listener to local LISTENER, and remote_listener to SCAN listener.

위의 SCAN에 대한 concept을 정리해보자면 RAC에 대한 virtual hostname 입니다. 이는 DNS에 설정되어 있고 이를 통해 DB에 접속하게 됩니다. failover나 load-balancing은 RAC 각 노드의 listener 들이 담당하게 됩니다.

이 내용은 "Note:887522.1 - 11gR2 Grid Infrastructure Single Client Access Name (SCAN) Explained" 를 참조했습니다

관련 문서와 동영상을 같이 링크 겁니다.  아직 한글로 소개된 자료는 없는 것 같네요.. 

[PDF] 

SINGLE CLIENT ACCESS NAME (SCAN)

 - [ 이 페이지 번역하기 ]
파일 형식: PDF/Adobe Acrobat - 빠른 보기
29 Mar 2010 ... Single Client Access Name (SCAN) is s a new Oracle Real Application Clusters (RAC)11g Release 2 feature that provides ...
www.oracle.com/technology/products/database/.../scan.pdf - 유사한 페이지






* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



제가 구독하는 블로그들 중 MWIDLAKE님이 포스트 한 내용입니다. 
한번 읽어 보고 정리해 봅니다 ~

10. 6. 17 작성자: mwidlake의 Martin Widlake's Yet Another Oracle Blog

If you look at v$session you sid SID and SERIAL#, which most of us DBA-types know uniquely identify a session and allow you to kill it (*with the relevant permissions and knowledge you are not about to compromise a business process).

But what is AUDSID?

desc v$session
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------
 SADDR                                              RAW(8)
 SID                                                NUMBER
 SERIAL#                                            NUMBER
 AUDSID                                             NUMBER
 PADDR                                              RAW(8)
 USER#                                              NUMBER
 USERNAME                                           VARCHAR2(30)
 COMMAND                                            NUMBER
 OWNERID                                            NUMBER
 TADDR                                              VARCHAR2(16)
 LOCKWAIT                                           VARCHAR2(16)
 STATUS                                             VARCHAR2(8)
 SERVER                                             VARCHAR2(9)
 SCHEMA#                                            NUMBER
 SCHEMANAME                                         VARCHAR2(30)
 OSUSER                                             VARCHAR2(30)
...

AUDSID is a unique identifier for the session and is used in sys.aud$ , as the SESSIONID column.


정리해 보면...

audsid는 auditing 기능을 위한 identifier 이며
sys.audses$ trigger에 의해 발생하는 unique value 이며
sys 계정의 audsid는 0 값을 가진다.. 

auditing 기능을 사용하고 있지 않아 더이상 깊이는 무리.. 


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



Oracle Certified Master는 IT 산업 최고의 자격증 OCM은 오라클 교육센터의 고급과정을 이수하면서 전문적인 기업에서 적어도 3~4년의 오라클 경험을 갖춘 Oracle Certified Professional(이하 OCP로 표기)을 위한 자격 인증이다. Oracle Certified Master가 되기 위해서 지원자는 OCP 자격증을 취득하고, 2개의 필수 고급 데이터베이스 관리자 과정을 오라클 교육센터에서 반드시 수강하고 난 이후에 OCM 시험을 통과해야만 한다.

오라클 교육센터 선임 강사들은 OCM 시험을 보기 위해서는 최소한 오라클을 사용한 경험이 3-4년 정도되야 하며, 5년 또는 그 이상의 경험을 하고 난 이후에 지원하기를 권장하고 있다. OCM 시험을 보기 전 준비해야 할 중요한 5가지 사항은 다음과 같다.

1. 지원자는 아래의 'OCM 응시를 위한 최소 권장 기술 및 경험'에 기술되어 있는 모든 기술사항을 갖추고 있어야 한다.
2. 올바른 구문(Syntax) 사용에 도움을 받을 수 있도록, 시험 진행 중에 제공되는 문서를 검색 및 활용할 수 있어야 한다.
3. 커맨드 라인 솔루션(Command Line Solutions)을 복습하고, 사용할 수 있도록 준비해야 한다. 비록 GUI에서 사용법을 알더라도 시험의 모든 부분에서 GUI가 사용 가능하지 않기 때문이다.
4. 모든 시험 내용에 대해서 시간을 가지고 충분히 실습을 해봐야 하며, 특히 정기적으로 사용하지 않는기술에 대해서 더욱 그러하다.
5. 고급 레벨의 개념적인 요구사항을 이해하여 구체적인 명령어와 그것을 실행하는데 필요한 조치를 할 수 있어야 한다. 시험을 통과하는데 있어서 다 년간의 경험 및 풍부한 실무능력이 지원자에게 필요한 이유가 여기에 있다.

OCM 응시자에게 요구되는 기본 요건

1. 3~4년 동안 전문적인 기업에서의 Oracle 사용 경험
2. 백업과 복구 및 복구 운영에서의 폭넓은 경험
3. SQL의 숙련된 활용
4. 다음과 같은 LUNUX 명령어에 대한 업무 지식:
 - 기본 OS 명령어를 구성하고 실행하기
 - 디렉토리 구조를 생성하고 검색하기
 - 복사, 이동, 삭제를 활용하여 문서 관리하기
 - Linux 환경의 텍스트 편집기
 - 환경변수 설정하기
5. 아래와 같은 오라 클 실행프로그램의 위치를 파악하고 실행시키는 능력
 - RMAN Utility
 - Oracle Net Manager
 - Oracle Net Configuration Assistant
 - OEM
 - Listener Utility
 - OMS
 - Oracle Password Utility
 - Database Creation Assistant
 - DGMGRL (for 11g OCM)
6. Oracle Enterprise Manager의 활용능력
7. 네트워킹을 구성하기 위한 Oracle Net Manager와 Oracle Net Configuration Assistant의 활용능력
8. Oracle Enterprise Server의 기술과 특징에 대한고급 지식을 이해하고 활용
 - 온라인 오라클 문서 검색
9. Konqueror 2.2 브라우저 소프트웨어의 활용능력 

더 자세한 내용은 아래 원문을 보세요~ 



* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!






Oracle Goldengate가 출시 되었습니다.
어떤 제품인가 하고 ETnew에 들어가서 보니 replication solution 이군요.
특이한건 이기종의 DB도 지원을 해준답니다.
이전에도 Oracle Gateway가 있었지만, 별로 많이 쓰이지도 않았고, 권하지도 았았죠.. ^^;

redo log file을 직접 capture 해서 target DB로 delivery 해주는 구조로 ADG나 Stream과 구조는 비슷한게 아닌가 싶네요.
near-real time으로 active-active 구현도 가능하다고 합니다.

- Disaster Recovery, Data Protection
- Zero Downtime, Migration and upgrade
- Operational Reporting
- Query Offloading  (데이터 자체를 다른 서버로 이동시켜 tx 처리)
- Data Distribution
- Real-time BI

firstData와 Overstock이라는 회사가 golden gate를 이용해 각각 8i, 9i에서 10g고 downtime 없이 upgrade 했다는 군요.
요즘 24*7으로 대부분 운영중이라 고려할 만한 solution 인거 같습니다.





 
오라클은 사용자 작업을 위해 많은 Package/Fuction 등 을 지원합니다. 
이런 놈들을 다 알필요는 없지만 아는 많큼 손발이 고생할 여지가 조금씩 줄어 듭니다. 그러니 기회가 있을 때마다 조금씩 알아 놓는게 좋겠죠 ^^;
얼마전 작업하다기 DBMS_SHARED_POOL.PURGE procedure를 유용하게 사용할 수 있는 기회가 있었어 간략하게 정리합니다. 
 
주말의 몇몇 table의 re-org 작업이 있었는데, 
시간 계산을 잘못해서 마지막 즈음에 기다리던 작업자를 위해 사용자 세션을 풀어 주었습니다. 주말이라 얼마나 들어오겠나 싶었죠.. 
많은 세션들이 들어오진 않았지만, 몇몇 세션들이 주로 수행되는 SQL을 이것 저것 수행하고 나갔습니다. 
 
근데 작업 전보다 성능이 않좋다고 하더군요. 
지금 re-org 작업이 있으니 조금 느릴 수도 있겠다 싶었죠. 근데, 작업 후에도 느리다고 하더군요. 
Plan이 바뀌었습니다. 통계정보도 같이 넣어 주었는데 말이죠.. 
 
import로 data를 loading 하면 마지막에 해당 segment의 통계정보를 같이 적제하게 됩니다. 근데 통계정보가 다 들어가기 전에 수행된 SQL은 통계정보가 없는 상태에서 cost를 계산해서 sql plan을 만들어 버리죠. 또 이렇게 만들어진 plan 정보는 해당 cursor가 purge 되기 전까지는 계속 사용하게 됩니다. 
 
이러한 비슷한 경우는 bind peeking 기능에 의해 일반적이지 않은 bind 값이 들어가도 발생할 수가 있습니다. 
 
이러한 경우 shared pool flush를 시켜 해당 cursor를 purge 시킬 수 도 있겠지만 11g 이후 부터는 단일 cursor 별로 purge가 가능합니다. 10.2.0.4 version에서도 사용가능한데, 이 버전의 경우 event 설정이 필요합니다. 
 
event="5614566 trace name context forever"
다음의 내용은 참조 노트의 사용 방법에 대한 간단한 예 입니다. 
 
SESSION 1 
 
sqlplus scott/tiger 
SQL> select ename from emp where empno=7900;
 
SESSION 2 
 
sqlplus / as sysdba 
 
SQL> select address, hash_value, executions, loads, version_count, invalidations, parse_calls 
     from v$sqlarea 
     where sql_text = 'select ename from emp where empno=7900';
 
ADDRESS          HASH_VALUE EXECUTIONS      LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS 
---------------- ---------- ---------- ---------- ------------- ------------- ----------- 
000000007A6CF430 1052545619          1          1             1             0           1
 
SQL> exec dbms_shared_pool.purge ('000000007A6CF430,1052545619 ','C'); 
 
SQL> select address, hash_value, executions, loads, version_count, invalidations, parse_calls 
     from v$sqlarea 
     where sql_text = 'select ename from emp where empno=7900';
 
no rows selected
 
 
이 내용은 아래의 문서를 참조했습니다. 
 
Note 457309.1 How To Flush an Object out the Library Cache 
Note 751876.1 DBMS_SHARED_POOL.PURGE Is Not Working On 10.2.0.4
 

Oracle 9i Release 2 Enterprise Edition 에서 소개된 TABLE Compress 기능은 블록 내에 저장되어 있는 데이터의 중복을 제거 함으로써 블록 내에 많은 데이터를 저장함으로써 저장공간의 효율성을 높이는 기술입니다.

반복되는 데이터를 블록의 시작 부분에  symbol table의 row로 생성하고 실재 row data는 이 row의 참조로 대체합니다. 해당 block의 row에 대한 데이터는 global symbol table이 아닌 해당 block내의 local symbol table로 만들어집니다.

따라서 블록에서 압축되지 않은 데이타를 다시 만드는데 필요한 모든 정보를 해당 블록 내에서 사용할 수 있습니다.

블록의 시작 부분에 있는 심볼 테이블을 제외하고 압축된 데이타베이스 블록은 일반 데이타베이스 블록과 비슷합니다.  결과적으로 일반 데이타베이스 블록에서 작동하는 모든 데이타베이스 기능은 압축된 데이타베이스 블록에서도 동일하게 작동한다고 합니다.

Table compress 기능은 storage의 높은 활용도와 질의시 적은 I/O양, buffer cache내의 압축된 형태 유지로 더 많은 데이터를 메모리 내에 유지하는 등의 장점을 갖고 있으나, DML 작업은 compress가 적용되지 않은 일반 table에 비해 느리며, CPU 사용률이 높아지는 단점도 가지고 있습니다.

compress의 경우 다른 고려 사항없이 compress 만 지정하면 oracle에서 자동으로 compress를 진행합니다. 대부분의 자료에서는 2:1 ~ 4:1 정도의 compress 비율을 말하지만 data의 속성, 군집 여부 등 많은 변수에 의해 편차가 많아 실 데이터의 sampling으로 compress 비율을 확인하는 것이 그나마 가장 확실 합니다.

compress는 동일 column data가 2개 이상이면 compress 대상이 되며, 서로 다른 column에 같은 값이 존재해도 이에 대해 compress를 하게 됩니다.

compress가 되는 시점은 한개의 block내에 pctfree에 도달하면 compress를 하며 compress 후 빈 공간에 non-compress row를 insert 하고 pctfree에 도달하면 다시 compress.. 를 반복하게 됩니다.

2010/05/04 Update:

UPDATE, INSERT가 많은 table에 대해서 COMPRESS optoin 사용은 자제 해야 되겠네요. 
이틀동안 UPDATE 문 성능으로 헤매다가 결국 OLTP COMPERSS 문제인 걸 확인했네요. --;

In general table compression is good for read only operations.Following is excerpt from "Table Compression" section of Data Warehousing Guide manual, which suggests that it is not a good idea to compress a table which expects a large update,because there are CPU overheads and big space consumption :
Table compression should be used with highly redundant data, such as tables with many foreign keys. You should avoid compressing tables with much update or other DML activity. Although compressed tables or partitions are updatable, there is some overhead in updating these tables, and high update activity may work against compression by causing some space to be wasted.






Faster Startup


The days when dinosaurs ruled the earth and 2GB memory was considered large are gone. Now, it's not uncommon to see large buffer caches to the tune of 100GB. When the instance is started, it might take several minutes, or even hours, to initialize a buffer cache of this size.

If you look deeper into the situation, you will notice that the entire buffer cache need not be up when the database instance starts. After the instance starts, the buffer cache is empty, which gradually fills up when users select data from tables. So, there is no need to initialize the entire buffer cache when the instance starts.

In Oracle Database 10g Release 2, this behavior is accounted for in the startup logic. When you start the instance, only 10% of the buffer cache is initialized; the rest is initialized after the database is opened by the checkpoint process. This new approach reduces instance startup time significantly.

Bear in mind, however, that until the entire buffer cache is initialized, automatic buffer cache sizing is not available.

아시다 시피 SGA memory 영역은 Database가 nomount 단계에서 할당됩니다. 
이 new feature는 nomount 단계에서는 10%의 buffer pool만 할당하고 나머지는 instance가 open 된 후에 할당한다는 의미입니다.


Drop Empty Datafiles


Imagine that you just added a datafile to the wrong directory or tablespace—a fairly common error. All is not lost; the datafile doesn't contain any data yet, so you can easily drop it, right?

Unfortunately, you can't. Prior to Oracle Database 10g Release 2, your only clean option for removing a datafile is to drop the entire tablespace and then rebuild it without that particular file. If the tablespace contains data, you have to go through the time-consuming and laborious process of storing the data on a separate location and reinstating it. In addition to its inconvenience, this process makes the tablespace unavailable.

Thankfully, in Oracle Database 10g Release 2 the process has been simplified: You can just drop the datafile. For example, the following command will remove the indicated datafile from the tablespace as well as from the server.
alter tablespace users drop datafile '/tmp/users01.dbf'
 /
There are a couple restrictions, however: The datafile must be empty to be dropped. You can't drop the last datafile in a tablespace; the tablespace itself must be dropped. And the tablespace must be online and in read-write status.

10g 이전 버전에서는 데이터파일을 잘 못 붙일 경우 이거 띄어 내려면 tablespace 전체를 재구성해야 하죠. 
예전 OPS 쓸때 raw device가 아닌 filesystem에 datafile을 추가하는 등의 황당한 경우도 있었습니다.. ㅋ
drop empty datafiles new feature는 이런 유저 실수로 인한 막대한 작업을 더이상 안해도 되게 해주겠군요. 


Catch the Error and Move On: Error Logging Clause


Suppose you are trying to insert the records of the table ACCOUNTS_NY to the table ACCOUNTS. The table ACCOUNTS has a primary key on ACC_NO column. It's possible that some rows in ACCOUNTS_NY may violate that primary key. Try using a conventional insert statement:
SQL> insert into accounts
  2  select * from accounts_ny;
insert into accounts
*
ERROR at line 1:
ORA-00001: unique constraint (ARUP.PK_ACCOUNTS) violated
None of the records from the table ACCOUNTS_NY has been loaded. Now, try the same with error logging turned on. First, you need to create a table to hold the records rejected by the DML statement. Call that table ERR_ACCOUNTS.
exec dbms_errlog.CREATE_ERROR_LOG ('ACCOUNTS','ERR_ACCOUNTS')
Next, execute the earlier statement with the error-logging clause.
SQL> insert into accounts
  2  select * from accounts_ny
  3  log errors into err_accounts
  4  reject limit 200
  5  /

6 rows created.
Note that the table ACCOUNTS_NY contains 10 rows yet only six rows were inserted; the other four rows were rejected due to some error. To find out what it was, query the ERR_ACCOUNTS table.
SQL> select ORA_ERR_NUMBER$, ORA_ERR_MESG$, ACC_NO
 2  from err_accounts;

ORA_ERR_NUMBER$   ORA_ERR_MESG$                                       ACC_NO
 ---------------  --------------------------------------------------  ------
               1  ORA-00001: unique constraint (ARUP.PK_ACCOUNTS) vi  9997
               olated
               1  ORA-00001: unique constraint (ARUP.PK_ACCOUNTS)vi  9998
               olated
               1  ORA-00001: unique constraint (ARUP.PK_ACCOUNTS) vi 9999
               olated
               1  ORA-00001: unique constraint (ARUP.PK_ACCOUNTS) vi 10000
               olated
Note the columns ORA_ERR_NUMBER$, which show the Oracle error number encountered during the DML statement execution, and the ORA_ERR_MESG$, which shows the error message. In this case you can see that four records were rejected because they violated the primary key constraint PK_ACCOUNTS. The table also captures all the column of table ACCOUNTS, including the column ACC_NO. Looking at the rejected records, note that these account numbers already exist in the table; hence the records were rejected with ORA-00001 error. Without the error-logging clause, the whole statement would have failed, with no records rejected. Through this clause, only the invalid records were rejected; all others were successful.

이 기능은 sql*loader의 bad file 같은 기능입니다. 
특정 에러가 발생해도 이를 logging만 하고 나머지 데이터는 처리를 해주는 군요.  
PK constraint violation 발생하면 이거 처리하는 것도 좀 귀찮은 작업인데, 요 기능 쓰면 약간 편해지겠습니다. ^^

그나 저나 아직도 10g new feature를 모르고 있다니... 좌절이다~



* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



11g에서 나온 PIVOT 구문입니다. 
아래 sample 처럼 동일 column 값에 대해 pivot 기능이 적용되어 display 됩니다. 

SQL> select job,deptno,avg(sal) from emp  group by job,deptno;

JOB                             DEPTNO   AVG(SAL)
--------------------------- ---------- ----------
PRESIDENT                           10       5000
MANAGER                             30       2850
CLERK                               30        950
CLERK                               10       1300
MANAGER                             20       2975
ANALYST                             20     6499.5
CLERK                               20        950
SALESMAN                            30       1400
MANAGER                             10       2450


SQL> select * from (select job,deptno,sal from emp) 
pivot (avg(sal) for deptno in (10,20,30)) order by job;

JOB                                 10         20         30
--------------------------- ---------- ---------- ----------
ANALYST                                    6499.5
CLERK                             1300        950        950
MANAGER                           2450       2975       2850
PRESIDENT                         5000
SALESMAN                                                1400


PIVOT 기능은 AWR 데이터를 보기편하게 변형하는 데 유용합니다. 

* 아래 SQL은 노드별 user call 값을 출력해본 간단한 SQL 입니다. 
select * from
(
 select to_char(end_interval_time,'HH24:MI:SS') end_interval_time
       ,a.instance_number,value from dba_hist_sysstat a, dba_hist_snapshot b
 where stat_name in ('user calls')
 and a.snap_id = b.snap_id
 and a.instance_number = b.instance_number
)
pivot (avg(value) for instance_number in (1 as "Node1",2 as "Node2",3 as "Node3"))
order by 1
/

END_INTERV                Node1      Node2      Node3
---------- -------------------- ---------- ----------
00:10:31          1,432,826,125 1278172133 1281672038
00:10:34          1,254,265,411 1153949372 1154503152
00:10:39            233,495,867  223300171  222547544
00:20:01          1,255,123,846 1154019492 1154577807
00:20:02          2,260,343,067 2050291466 2048154492
00:20:08            719,183,716  664321484  663506525
00:20:13            478,942,298  446272763  444528572


* V$SYSSTAT의 특정 statistic 값을 query하는 SQL 
select *
from (select to_char(sysdate,'MMDDHH24MISS') dat, a.name,a.value
        from v$sysstat a 
        where statistic# in (146,9,67,62,72,6,446,447,0,451,5,4)
        )
pivot (sum(value) for name in ('logons cumulative','user rollbacks','user commits','user calls','session logical reads','physical reads','db block changes', 'physical writes','redo size','parse count (total)','parse count (hard)','execute count'))
order by dat
/

* PIVOT을 decode로 바꿔본 SQL (11g 이전 버전)
select to_char(sysdate,'MMDDHH24MISS') dat,
       sum(decode(name,'logons cumulative',value)) "logons cumulative",
       sum(decode(name,'user rollbacks',value)) "user rollbacks",
       sum(decode(name,'user commits',value)) "user commits",
       sum(decode(name,'user calls',value)) "user calls",
       sum(decode(name,'session logical reads',value)) "session logical reads",
       sum(decode(name,'physical reads',value)) "physical reads",
       sum(decode(name,'db block changes',value)) "db block changes",
       sum(decode(name,'physical writes',value)) "physical writes",
       sum(decode(name,'redo size',value)) "redo size",
       sum(decode(name,'parse count (total)',value)) "parse count (total)",
       sum(decode(name,'parse count (hard)',value)) "parse count (hard)",
       sum(decode(name,'execute count',value)) "execute count"
from v$sysstat
where statistic# in (146,9,67,62,72,6,446,447,0,451,5,4)
group by to_char(sysdate,'MMDDHH24MISS')
/
(왠지 좀 무지해 보이는데.. 더 좋은 방법이 있으면 알려주세요 *^^*)


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



아래 내용은 오라클 관련 Blog에서 DBA를 구한다고 올라온 Post 입니다. 

요즘 가끔 네이버지식에 들어가서 질문에 답을 달고 있는데요, 
DBA라는 직업에 대한 이야기들이 많이 나오더군요. 
그래서 도움이 되지 않을까 해서 한번 올려봅니다. 

DBA를 꿈꾸시는 분들은 참고하세요 ~
(사실 이정도 하시는 분들 찾긴 힘들죠. 저도 마찬가지지만.. ^^;) 

혹시 아래 글 보고 여기 취직해보고 싶으신 분은 아래 링크로.. 

Job Summary: Oracle Database Administrator (DBA)

The Oracle DBA will be supporting multiple environments from Development, Quality Assurance (QA) and Production databases running Oracle 10g in a clustered environment. Experience working in a production UNIX/Linux environment is required for this position. Experience in performance tuning, change implementation, backup and recovery, monitoring and installation are key requirements. Candidate will also be expected to provide application-level support for our in house J2EE applications running on Tomcat and OC4J. Ideal candidate will be a self-starter and a team player with a strong organization, process and communication skills. This is a permanent position, not a contract. No 3rd parties please. No H1's or L1's.

Job Description

Installation and patching of Oracle RDBMS on Linux – adhering to standard operating procedures
Performance tuning and administrative functions on Oracle production databases
Enforce best practices in all areas of database administration and architecture including
Review and implement database changes
Participate in 24x7 on-call rotation for production databases
Ensure backup and recovery of all Oracle data using RMAN, Standby Database and import/export
Develop scripts for reporting, data manipulation and automation of daily tasks
Provide support to Development and QA teams on applications/database issues
Engage and support Software Developers during the SDLC
Administration and support of Oracle’s Business Intelligence, Informatica, Tomcat and OC4J applications
Develop and document formal processes and procedures

Job Requirements

Computer Science, or related science/Engineering degree (B.S. or equivalent).
At least 3 to 5 years production Oracle DBA experience in a Linux/UNIX environment
At least 2 years of experience with Oracle Real Time Application Clusters 10g or 11g with ASM or NFS.
UNIX/Linux system knowledge sufficient to configure, maintain and monitor Oracle instance(s)
Experience with OLTP, OLAP, DW, and ETL concepts
Experience with indexing strategies and reading explain plans
Experience with parallel processing, and partitioning
Experience with Oracle Data Guard
Experience with Oracle Grid Control, especially monitoring and alerting and managing multiple databases
Database performance tuning ability is required
Familiarity with the Full Software Development Lifecycle (SDLC)
Demonstrated knowledge of Oracle and Oracle tools to support database environments
Demonstrated knowledge of shell environments (C, Korn, KSH, Bourne)
Demonstrated proficiency of SQL and PL/SQL
Familiarity with HTML/ JAVA /Java scripts / JSP / PERL is a plus
Familiarity with Oracle’s Business Intelligence suite, Informatica and J2EE administration is a plus.
Will require after-hours or occasional weekend work to make changes during outage windows.
Excellent oral and written skills




* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



Oracle 관련된 전문 블로거들의 RSS를 구독하고 있습니다. 
좀 흥미로운 내용이 있어 소개해 드립니다. 

Did you know that it’s possible to use EXPLAIN PLAN FOR CREATE INDEX ON table(col1,col2,col3) syntax for explaining what exactly would be done when an index is created?

That’s useful for example for seeing the Oracle’s estimated index size without having to actually create the index.

You can also use EXPLAIN PLAN FOR ALTER INDEX i REBUILD to see whether this operation would use a FULL TABLE SCAN or a FAST FULL INDEX SCAN (offline index rebuilds of valid indexes can use this method).


위의 내용은 읽어 보시면 아시겠지만, EXPLAIN PLAN FOR 명령을 이용해 생성할 INDEX의 size를 추측해 보는 방법을 설명하고 있습니다. 
EXPLAIN PLAN FOR는 일반적으로 수행행되는 SQL의 PLAN이나 statistic 값들을 확인하기 위해 사용되는데, 
해당 SQL이 수행되면서 읽을 양으로 INDEX size를 판단할 수 있다는 내용입니다. 

위 포스트에서 설명한 내용을 그대로 한번 따라가 보겠습니다. 

SQL> show user
USER is "SCOTT"
SQL> explain plan set statement_id = 'cr_emp_idx01' for  create index emp_idx01 on emp(empno);   

Explained.

SQL> @?/rdbms/admin/utlxpls

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 188079254

------------------------------------------------------------------------------------
| Id  | Operation              | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | CREATE INDEX STATEMENT |           |    14 |    56 |    13   (0)| 00:00:01 |
|   1 |  INDEX BUILD NON UNIQUE| EMP_IDX01 |       |       |            |          |
|   2 |   SORT CREATE INDEX    |           |    14 |    56 |            |          |
|   3 |    TABLE ACCESS FULL   | EMP       |    14 |    56 |    12   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Note
-----
   - estimated index size: 65536  bytes

14 rows selected.

위의 plan 결과에 따르면 해당 index는 65536 bytes가 되겠군요.
그럼 INDEX를 한번 만들어 보겠습니다.

SQL> create index emp_idx01 on emp(empno);

Index created.

SQL> column segment_name format a30
SQL> column segment_type format a30
SQL> select segment_name,segment_type,bytes from user_segments where segment_name= 'EMP_IDX01';

SEGMENT_NAME                   SEGMENT_TYPE                        BYTES
------------------------------ ------------------------------ ----------
EMP_IDX01                      INDEX                             1048576

SQL>  

SQL> connect system/manager
Connected.

SQL> select segment_name,segment_type,tablespace_name from dba_segments where segment_name = 'EMP_IDX01'; 

SEGMENT_NAME                   SEGMENT_TYPE                   TABLESPACE
------------------------------ ------------------------------ ----------
EMP_IDX01                      INDEX                          TS_TEST01


SQL> column tablespace_name format a10
SQL> select TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT from dba_tablespaces where tablespace_name = 'TS_TEST01';

TABLESPACE INITIAL_EXTENT NEXT_EXTENT
---------- -------------- -----------
TS_TEST01         1048576     1048576

EMP_IDX01이 저장될 tablespace의 initial extent 값이 1048576이라
INDEX size 65536 bytes는 한개의 extent에 모두 저장되었군요.

PLAN에서 보여준 statistic 값은 Block scan 결과만 보여주는 것이니 PCTFREE 등의 값의 영향으로 약간의 가감은 필요할 것 같습니다만.
대충 얼마정도의 공간이 필요할 것이다라는 것에 대한 힌트는 될 것 같습니다.



* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!





Abstract

This paper will present how queries involving database links  are processed.  We  will look  at  four cases:  (1) query against a single remote table, (2) a join involving one local table and one remote table, (3) a join of two tables located on the same remote database, and (4) a join of two tables existing on  two  separate remote databases.

Introduction

The method Oracle uses to process distributed queries is  one  of  the  less   understood   features  offered    by   Oracle.   This presentation will explain some of the things that  happen  behind the  scenes  of a distributed query and will give some techniques an application developer can  use  to  write  better  distributed queries.

SQL*Net Demystified

In order to perform a distributed query, an RDBMS needs to have a means of communicating with other databases.  SQL*Net is Oracle's remote  data  access  protocol   and   application   programmatic interface  (API)  that runs on top of existing network protocols.  Its main function is to allow a  front-end  application  such  as SQL*Forms  to  run  on  one  computer while accessing Oracle data which resides on a database either on the same machine  or  on  a remote machine. 

Architecturally, the front-end tool is responsible for generating SQL statements depending upon user input (eg user fills in fields in a form and then hits the  INSERT  key)  or  application design (eg   embedded  SQL  in a C program).  We also refer to this as a client process.  The Oracle  back-end  or   server   process   is responsible for parsing and executing SQL statements as optimally as possible.  Once processed, the results of  the  statement  are returned  to  the  front-end  tool.   In  the  case  of  a SELECT statement, the server  process  retrieves  a  record  or  set  of records  from  the  datafiles  and  sends  them  the  client upon request.  The  front-end  tool  then  decides  how  the  data  is presented  to the user.  This leaves SQL*Net with the deceptively simple tasks of managing  a  communication  session  between  two computers, transporting data between two processes, and providing any necessary character set conversions.   Since  SQL*Net  itself has  no role in the decision making process of executing a query, one can say that this paper is actually an RDBMS topic in SQL*Net clothing!

The Sample Environment

For the purposes of this paper, we will use a sample  environment consisting of:
  • three computers running an OS such as Unix (identified as unix1, unix2, and unix3) connected via some networking protocol such as TCP/IP.
  • an Oracle database running on each machine (identified as instance A, B, and C respectively) 
  • an Oracle database user account of scott/tiger on each database

We will assume that our user, scott, is already logged onto unix1 and has initiated a SQL*Plus session with database A.  Theoretically, it should be possible for the three  nodes  to  be running  any  of the operating systems supported by Oracle and be able to communicate with any supported networking protocol.  Some environments,  however,  will  present some minor limitations not covered in this paper.   For example,  DOS cannot act as a server to other machines.

Database Links

In order for two Oracle  databases  to  share  data,  one  Oracle instance  temporarily  acts  as  a  client  to  the  other Oracle instance.  This action  is accomplished  through  database  links stored  in  the  initiating  database.  The syntax for creating a database link is as follows (optional clause enclosed by []):

  CREATE DATABASE LINK dblinkname
        [CONNECT TO user IDENTIFIED BY password]
        USING 'connect_string'

For our example, we initially  create  two  database  links  from unix1 to unix2 and unix3 as follows:

       CREATE DATABASE LINK lax
           USING 'T:unix2:B';

       CREATE DATABASE  LINK syd
           USING 'T:unix3:C';
 
    SQL*Net V2 based DBLINKs using a V2 service name example:
 
       CREATE DATABASE LINK lax
           USING 'v2servicename';
                  -or-
         CREATE DATABASE LINK lax
           USING 'TNS:v2servicename';


Simple Remote Queries
 
Before we look at what happens with a complex  distributed  query involving  joins of tables on  sereral remote databases, it helps to consider what the mechanics are behind a simple query using  a database link.  We will use the following example SQL statement: 

    SELECT MAX(ename), 'dept # =' || deptno
        FROM emp@syd
        WHERE deptno BETWEEN 10 AND 100
        GROUP BY deptno
        ORDER BY 1;

The local database on unix1 will process the query and  send  the following to the database on unix3: 

    SELECT ename, deptno
        FROM emp
        WHERE deptno >= 10 AND deptno <= 100;

As the records are fetched into unix1, it performs the  group  by applies  the MAX() function to each group then orders what it has and sends those results back to its client.  This implies several important points about how a remote query is handled  by  Oracle  V6.   Some  are not easily implied but noted

below:
 
     1. Aggregate functions like MAX(), COUNT() are NOT passed across the net but rather are performed on the local node.
     2. Expressions in the SELECT list are decomposed into columns and evaluated when the data is retrieved.
     3. Only a relevant subset of columns are fetched across the net.
     4. An expression in a WHERE clause is passed across to the remote database if it compares the remote column to a literal (eg ename = 'KING').
     5. Expressions in a WHERE clause are passed to the remote database if all columns are in the expression are located in the same remote table the remote database (eg emp.sal * 0.20 > emp.bonus)
     6. Datatype conversion functions like TO_CHAR() in a WHERE clause are subject to the conditions in #4 and #5.
     7. The optimizer only has knowledge of local indexes when making decisions about how to execute a query.
     8. Remote indexes can be still be used to resolve the decomposed query sent to the remote database.
     9. GROUP BY is not sent to the remote database.
    10. ORDER BY is not sent to the remote database.

 
Simple Distributed Joins

With joins that involve tables on a remote database and  a  local or  second remote database, the points mentioned in the case of a simple remote query are still true.  What happens to  allow  this is  the decomposition of a join into separate independent queries whose results are then joined on  the  local  node.   Here  is  a simple example of how a join is decomposed.
 
    SELECT ename, dname
        FROM emp@syd e, dept@lax d
        WHERE e.deptno = d.deptno
        AND e.job != 'CLERK'
        AND d.loc = 'NEW YORK';

becomes:

unix3:   SELECT ename, job, deptno
             FROM emp
             WHERE job <> 'CLERK';
 
unix2:   SELECT dname, loc, deptno
             FROM dept
             WHERE loc = 'NEW YORK';

Note that, at least in Oracle V6, the  same decomposition  occurs even if both tables exist on the same remote node.
 
Putting It All Together

With these facts in mind, it is easy to see how the use of  views can help in cases where it is clearly better for a function to be performed on a remote node,  rather  than  the  local  one.   For example,  instead  of  issuing  a  count of rows against a remote database and having the data returned to be  counted  locally,  a remote  view  could  be  queried  to return only the count value. This increases performance by reducing network traffic.

Example:

    SELECT COUNT(*)
        FROM emp@syd
        WHERE deptno = 10;

becomes...
 
unix3:

    CREATE VIEW empcount (numemps,  deptno) AS
        SELECT COUNT(empno), deptno
            FROM emp
            GROUP BY deptno;

unix1:

    SELECT numemps, deptno
        FROM empcount@lax
        WHERE deptno = 10;

Views can also be used to help control the node  where  the  join will  actually  take  place.   In the case where there is a small table on the local  database  and  a  large  table  on  a  remote database,  it  is  usually  better to have the smaller table sent across the network to be processed  remotely  than  retrieve  the large  table  and perform a local join.  This method requires the existence of database links from each of the  three  machines  to the other two.
 
Example:

    SELECT ..
        FROM small, big@syd
        WHERE small.key=big.key;

becomes...
 
unix2:

    CREATE VIEW bigsmall AS
        SELECT ..
            FROM small@mia, big
            WHERE small.key=big.key;
 
unix1:

    SELECT ..
        FROM bigsmall@syd;

When both tables being joined are on the same  remote  node,  one can  use  a view to make sure the join is performed on that node. At times, the above scenario exists in a subtle  form.   Consider the following query:
 
    SELECT *
        FROM A@mia a, B@lax b, C@mia c
        WHERE a.x = b.x
        AND b.x = c.x;

Upon examining the WHERE clause, one  sees  that  the  transitive expression  of "a.x = c.x" can also be generated. This shows that tables A and C can be joined at the same remote node rather  than being joined at the local node.  The predicates taken directly do not always show that a remote join is possible.
 
In the case where both tables are on separate databases  one  can create  a view on the machine where the join may be performed the quickest.  While deciding this, one can consider which  node  has the largest table, the fastest CPU, or the lightest load.
 
If views are not  possible,  it  may  be  possible  to  fool  the optimizer  into choosing a different path that may be faster than what the rules would predict.  For example if one were joining  a subset of a local small dept table with a large remote emp table, a nested loops join may return faster than a sort merge.  Here is an example.

unix1:

    SELECT e.ename, d.dname
        FROM emp@hq e, dept d
        WHERE d.loc IN ('BUTTE', 'FLAGSTAFF')
        AND e.deptno = d.deptno;
   
In the above query, the ename and deptno columns of the whole emp table  will  be  pulled  over  the  net to have it's deptno value compared with the department numbers of  departments  located  in Butte,  Montana  and  Flagstaff, Arizona.  If the total number of employees working in those cities are a small percentage  of  the total  employees working worldwide, then much network traffic and IO was wasted  reading  and  sending  data  that  would  just  be rejected. 

If emp had an index on the deptno column, it would  be  ideal  to just  have  it  make an index scan for rows that have departments located in the two cities we want  and  just  return  those  rows back.   The following query will persuade the optimizer to choose that execution path. 

unix1:
    SELECT e.ename, d.dname
        FROM emp@hq e, dept d
        WHERE d.loc IN ('BUTTE', 'FLAGSTAFF')
        AND e.deptno <= d.deptno
        AND e.deptno >= d.deptno

Note that the last two clauses taken together have the same logic as  a  straight  equality.   However, the optimizer analyzes each clause and concludes that it will have to do a  full  table  scan for each dept.deptno. 

In this case, Oracle performs a nested loops join and  sends  the following query to the remote database:
 
    SELECT ename, dept
        FROM emp
        WHERE deptno >= :1
        AND deptno <=: 2;

It then loops through the appropriate rows  in  dept,  binds  the deptno values and executes the remote query. 
One can also use the TKPROF and EXPLAIN utilities as another  way to  see  how  queries are processed.  To enable these facilities, one may turn on global tracing by setting sql_trace = true in the init.ora  file.   Then one may simulate a distributed database by creating and using database links that loop back to the  database where  the  query  originated.   This  will create multiple trace files -- one  for  the  "local"  session  and  another  for  each "remote"  connection  query.  If one had to, one could copy trace files from a remote machine and use the  EXPLAIN  parameter  over SQL*Net with the command "tkprof ..  EXPLAIN=user/pswd@remote."

Note 1004553.6 DISTRIBUTED QUERY ANALYSIS.



* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



oracle 11g 부터는 alert, trace file 등의 관리방식이 ADR이라는 새로운 방식으로 바뀌었습니다.
이전에 ADRCI를 이용해 IPS하는 방법에 대해 포스트 하나 올렸었는데, 
오늘은 trace file, incident 등을 정리하는 purge 기능에 대해 소개합니다. 

이전 버전에서 log, trace file 등의 정리는 O/S 명령을 통해 정리해 주곤 했죠. 
이 과정에 redo log file을 지우는 등의 사고도 가끔 발생했었죠. 

사실 adrci의 purge 명령은 설명할 내용이 별로 없을 정도로 간단합니다. ^^;
adrci로 들어가서 HOME을 지정한 후 삭제할 기간(min)이나 incident를 지정해 주면 됩니다. 

adrci> help purge

  Usage: PURGE [[-i <id1> | <id1> <id2>] | 
               [-age <mins> [-type ALERT|INCIDENT|TRACE|CDUMP|HM|UTSCDMP]]]: 

  Purpose: Purge the diagnostic data in the current ADR home. If no
           option is specified, the default purging policy will be used.

  Options:
    [-i id1 | id1 id2]: Users can input a single incident ID, or a 
    range of incidents to purge.

    [-age <mins>]: Users can specify the purging policy either to all
    the diagnostic data or the specified type. The data older than <mins>
    ago will be purged

    [-type ALERT|INCIDENT|TRACE|CDUMP|HM|UTSCDMP]: Users can specify what type of 
    data to be purged.

  Examples:  
    purge 
    purge -i 123 456
    purge -age 60 -type incident

쓰고 보니 별 내용이 없습니다. 
근데, ADR관련해서는 IPS와 purge 명령만 알면 거의 필요한 기능은 다 안거 같네요.. 뭐가 또 있을 라나..


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



다음은 일반 테이블을 partition table로 online redefinition기능을 이용해 변경하는 예제입니다. 

SCOTT.EMP_REDEF table은 HIREDATE가 varchar2로 정의되어 있는데, 
partition table을 day interval로 하기 위해서 HIREDATE를 date type으로 바꿔줘야 합니다. 
online redefinition 기능을 이용해서 HIREDATE column 값을 이용해 hir_date 라는 date column을 추가하고 
partition으로 변경합니다.

1. table 생성 및 데이터 입력

CREATE TABLE SCOTT.EMP_REDEF
(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE varchar2(8),
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2)) tablespace USERS;

alter table SCOTT.emp_REDEF add constraint emp_pk primary key (empno);

INSERT INTO SCOTT.EMP_REDEF VALUES (7369, 'SMITH', 'CLERK', 7902,'20100415', 800, NULL, 20);
commit;

2. redefinition 가능 여부 판단. 
exec dbms_redefinition.can_redef_table('SCOTT', 'EMP_REDEF');

3. 임시 table 생성 
create table scott.emp_REDEF2
    (empno number primary key,
    ename varchar2(10),
    designation varchar2(9),
    mgr number(4),
    hiredate varchar2(8),
    hir_date date,
    sal number(7,2),
    comm number(7,2),
    deptno number(2)
    ) 
partition by range (hir_date) interval (numtodsinterval(1,'DAY'))
( partition p_before_1_jan_2005 values  less than (to_date('20050101','yyyymmdd')))
tablespace USERS
/

4. redefinition 지정.
alter session set nls_date_format = 'yyyymmdd';
exec dbms_redefinition.start_redef_table('SCOTT','EMP_REDEF','EMP_REDEF2', 'EMPNO EMPNO, ENAME ENAME, JOB DESIGNATION, MGR MGR, HIREDATE HIREDATE, to_date(hiredate) hir_date, SAL SAL,COMM COMM,DEPTNO DEPTNO');

5. data sync
exec dbms_redefinition.sync_interim_table('SCOTT','EMP_REDEF','EMP_REDEF2');

6. finish 
exec dbms_redefinition.finish_redef_table('SCOTT','EMP_REDEF','EMP_REDEF2');

7. 임시 table 삭제. 
drop table scott.emp_REDEF2;

8. 원본 데이터 변경 확인. 

SQL> select * from scott.emp_REDEF;

     EMPNO ENAME                          DESIGNATION                        MGR HIREDATE                 HIR_DATE        SAL       COMM     DEPTNO
---------- ------------------------------ --------------------------- ---------- ------------------------ -------- ---------- ---------- ----------
      7369 SMITH                          CLERK                             7902 20100415                 20100415        800                    20

SQL> desc scott.emp_REDEF
 Name                                                                                                              Null?    Type
 ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------
 EMPNO                                                                                                             NOT NULL NUMBER
 ENAME                                                                                                                      VARCHAR2(10)
 DESIGNATION                                                                                                                VARCHAR2(9)
 MGR                                                                                                                        NUMBER(4)
 HIREDATE                                                                                                                   VARCHAR2(8)
 HIR_DATE                                                                                                                   DATE
 SAL                                                                                                                        NUMBER(7,2)
 COMM                                                                                                                       NUMBER(7,2)
 DEPTNO                                                                                                                     NUMBER(2)

SQL> select table_name,PARTITION_NAME,HIGH_VALUE from dba_tab_partitions where table_name = 'EMP_REDEF';

TABLE_NAME                                                                                 PARTITION_NAME
------------------------------------------------------------------------------------------ -----------------------------------------
HIGH_VALUE
--------------------------------------------------------------------------------
EMP_REDEF                                                                                  P_BEFORE_1_JAN_2005
TO_DATE(' 2005-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA

EMP_REDEF                                                                                  SYS_P41
TO_DATE(' 2010-04-16 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA




* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



요즘 IT의 화두 중 주목 받는 화두가 클라우드 기술입니다.
구글, 아마존 등 여러 서비스 업체들이 이를 위해 많은 준비를 해왔고 또 주도하고 있습니다.
기존의 IT를 주도하던 대형 업체들이 이들을 따라가는 모양새인 듯 한데요..

Oracle Home page에 보면 오라클도 cloud 기술에 대해 많은 준비를 하고 있는 듯 한데,
oracle 11g release 2에서 클라우드 기술을 이용해 지원하는 amazon AWS service로 backup을 소개하는 좋은 자료가 있어 post 해봅니다.

Backup to Amazon Simple Storage Service (S3) Using OSB Cloud Computing  (oracle 11g R2)

Oracle now offers backup to Amazon S3, an internet-based storage service, with the Oracle Secure Backup (OSB) Cloud Module. This is part of the Oracle Cloud Computing offering. This feature provides easy-to-manage, low cost database backup to Web services storage, reducing or eliminating the cost and time to manage an in-house backup infrastructure.

amazon AWS service로 backup에 대한 자세한 설명은 아래의 presentation을 보시면 확인하실 수 있습니다.

presentation을 보시면 아시겠지만 
DB size 500G정도면 backup time이 4시간, incremental backup time 30분, $200/month 이면 가격도 훌륭해 보이는 군요.  
더구나 디스크 구입이나 유지보수 없이, 또 용량 증설도 간단하니 향후 고려해 볼만한 구조가 아닐까 싶습니다. 

오라클의 클라우드 관련 문서 몇개 링크 겁니다.


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



Oracle Database Migration이나 데이터 정리 등을 하려 TRUNCATE 명령 등을 수행할 때 ORA-2266에러를 만날 수 있습니다. 
요 에러는 reference constraint key가 걸려 있어 명령을 수행할 수 없다는 에러인데, 내가 작업하려 하는 table의 PK를 누가 참조하고 있다는 의미죠. 

> oerr ora 2266
02266, 00000, "unique/primary keys in table referenced by enabled foreign keys"
// *Cause: An attempt was made to truncate a table with unique or 
//         primary keys referenced by foreign keys enabled in another table.
//         Other operations not allowed are dropping/truncating a partition of a
//         partitioned table or an ALTER TABLE EXCHANGE PARTITION.
// *Action: Before performing the above operations the table, disable the 
//          foreign key constraints in other tables. You can see what 
//          constraints are referencing a table by issuing the following 
//          command:
//          SELECT * FROM USER_CONSTRAINTS WHERE TABLE_NAME = "tabnam";

이런 경우 dba_constraints를 query해서 어떤 table에서 reference 하고 있는지 확인할 수 있습니다. 
간단한 SQL이지만 계속 만들기 귀찮아 한번 정리해 봅니다. 

column r_owner format a20
column r_constraint_name format a30
column owner format a20
column table_name format a30
column constraint_name format a30
column "Constraint Disable COMMAND" format a150
set linesize 200
set pagesize 200
select r_owner,r_constraint_name,owner,table_name,constraint_name,constraint_type
from dba_constraints
where r_constraint_name in (select constraint_name from dba_constraints where table_name = upper('&&TABLE_NAME'))
/
select 'alter table '||owner||'.'||table_name||' disable constraint '||constraint_name||';' "Constraint Disable COMMAND"
from dba_constraints
where r_constraint_name in (select constraint_name from dba_constraints where table_name = upper('&TABLE_NAME'))
/

위의 SQL을 돌리면 아래 처럼 reference 하고 있는 table과 해당 constraint가 나옵니다. 
또 요놈들을 disable 해 줄 수 있는 명령도 같이 출력하게 됩니다. 

R_OWNER              R_CONSTRAINT_NAME              OWNER                TABLE_NAME                     CONSTRAINT_NAME                CON
-------------------- ------------------------------ -------------------- ------------------------------ ------------------------------ ---
DBSNMP               BSLN_BASELINES_PK2             DBSNMP               BSLN_STATISTICS                BSLN_STATISTICS_FK             R
DBSNMP               BSLN_BASELINES_PK2             DBSNMP               BSLN_THRESHOLD_PARAMS          BSLN_THRESHOLDS_FK             R

Constraint Disable COMMAND
------------------------------------------------------------------------------------------------------------------------------------------------------
alter table DBSNMP.BSLN_STATISTICS disable constraint BSLN_STATISTICS_FK;
alter table DBSNMP.BSLN_THRESHOLD_PARAMS disable constraint BSLN_THRESHOLDS_FK;

물론 아래처럼 cascade로 다 disable 시킬 수 있지만, 눈으로 한번 확인하고 작업하는 이 신중함 땜에.. ㅋ

ALTER TABLE dept DISABLE PRIMARY KEY CASCADE;


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



DECODE() Function는 return된 결과가 지정된 값과 동일할 경우 특정 value를 출력해주는 function이다.  DECODE()는 다음과 같은 형태로 사용된다.

DECODE(value, search_value, result, default_value)

위의 decode function은 미리 지정된 value와 search_value가 같을 경우 result를, 그렇지 않은 경우 default_value를 출력한다. 이와 같이 decode()는 SQL에서 PL/SQL없이 IF-THEN-ELSE logic을 구현하고 있다.

다음은 decode()의 간단한 동작 예이다.

SELECT DECODE(1, 1, 2, 3)
FROM dual;

DECODE(1,1,2,3)
---------------
              2


SELECT DECODE(1, 2, 1, 3)
FROM dual;

DECODE(1,2,1,3)
---------------
              3

다음의 예는 more_products table의 available column의 값을 비교해 원하는 string을 출력한다. available column의 값이 'Y'일 경우 "Product is available'을 출력하고, 'Y'가 아닐 경우 'Product is not available"을 출력한다.

SELECT prd_id, available,
   DECODE(available, 'Y', 'Product is available',
      'Product is not available')
FROM more_products;

    PRD_ID A DECODE(AVAILABLE,'Y','PR
---------- - ------------------------
         1 Y Product is available
         2 Y Product is available
         3 N Product is not available
         4 N Product is not available
         5 Y Product is available

다음은 product table의 product_type_id column의 값들에 따라 원하는 string을 출력한다. 즉 product_type_id가 1일 경우 'Book', 2일 경우 'Video', 3일 경우 'DVD', 4일 경우 'CD', 기타 다른 값일 경우 'Magazine'을 출력한다.

SELECT product_id, product_type_id,
 DECODE(product_type_id,
   1, 'Book',
   2, 'Video',
   3, 'DVD',
   4, 'CD',
   'Magazine')
FROM products;

PRODUCT_ID PRODUCT_TYPE_ID DECODE(P
---------- --------------- --------
         1               1 Book
         2               1 Book
         3               2 Video
         4               2 Video
         5               2 Video
         6               2 Video
         7               3 DVD
         8               3 DVD
         9               4 CD
        10               4 CD
        11               4 CD
        12                 Magazine

Decode()은 CASE문에 비해 depth가 깊어지면 성능이 떨어지는 것으로 알려져 있다. depth가 깊은 SQL의 경우 CASE()와의 성능 비교가 필요할 수 있다.


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



Active DataGuard 모니터링하는 SQL script를 만들어 보았습니다.
수행환경은 oracle 11g release 1 입니다.

1. 현재 dataguard 관련 process 모니터링
2. 마지막 전송받은 archived log file
3. Primary와 Standby 간의 GAP, 지연 정보 등

column process format a10
column status format a15
column client_pid format a10
column group# format a10
column name format a60
set linesize 200
alter session set nls_date_format = 'MM/DD HH24:MI:SS';
select PROCESS,PID,STATUS,CLIENT_PROCESS,CLIENT_PID,GROUP#,THREAD#,SEQUENCE#,DELAY_MINS,BLOCK#,BLOCKS from V$MANAGED_STANDBY
where status not in ('IDLE','CLOSING')
order by status
/
select b.NAME,b.DEST_ID, b.THREAD#,b.SEQUENCE#,b.STANDBY_DEST,b.ARCHIVED,b.APPLIED,b.STATUS,b.COMPLETION_TIME
from 
(select thread#,max(sequence#) sequence from V$ARCHIVED_LOG group by thread#) a, v$archived_log b
where a.thread# = b.thread# and a.sequence = b.sequence# 
/
column name format a30
column value format a50
column TIME_COMPUTED format a30
column unit format a30
select * from V$DATAGUARD_STATS
/

PROCESS           PID STATUS          CLIENT_PROCESS           CLIENT_PID GROUP#        THREAD#  SEQUENCE# DELAY_MINS     BLOCK#     BLOCKS
---------- ---------- --------------- ------------------------ ---------- ---------- ---------- ---------- ---------- ---------- ----------
MRP0            11615 APPLYING_LOG    N/A                      N/A        N/A                 1      47741          0     214659    1024000
ARCH             9762 CONNECTED       ARCH                     9762       N/A                 0          0          0          0          0


NAME                                                            DEST_ID    THREAD#  SEQUENCE# STANDBY_D ARCHIVED  APPLIED                     STATUS          COMPLETION_TIM
------------------------------------------------------------ ---------- ---------- ---------- --------- --------- --------------------------- -------------
/ARC2/2_21989_697581426.arc                             1          2      21989 NO        YES       YES                         A               03/23 14:39:46
/ARC3/3_21296_697581426.arc                             1          3      21296 NO        YES       YES                         A               03/23 15:06:36
/ARC1/1_47740_697581426.arc                             1          1      47740 NO        YES       IN-MEMORY               A               03/23 16:05:58


NAME                           VALUE                                              UNIT                           TIME_COMPUTED
------------------------------ -------------------------------------------------- ------------------------------ ------------------------------
apply finish time              +00 00:00:03.5                                     day(2) to second(1) interval   23-MAR-2010 16:24:19
apply lag                      +00 00:00:00                                       day(2) to second(0) interval   23-MAR-2010 16:24:19
estimated startup time         32                                                 second                         23-MAR-2010 16:24:19
standby has been open          N                                                                                 23-MAR-2010 16:24:19
transport lag                  +00 00:00:00                                       day(2) to second(0) interval   23-MAR-2010 16:24:19






서점에서 몇번 오라클 관련 서적을 샀었는데, 많이 실망한 적이 많이 있었습니다.
그때는 오라클에 대해 잘 모를 때였던 거 같은데,
나중에 보니 tablespace를 작업공간이라고 해석해 놓았던 책도 있더군요.. --;

다음의 리스트는 오라클 전문가가 되기 위해 읽을만한 추천책입니다.

물론 이제 막 십년 밖에 안된 야매인 제가 추천해드리는 책은 아니고,
http://oracledoug.com 블로그를 운영하는 "Douglas Ian Burns"라는 사람이 추천한 책입니다.
이분은 자그마치 18년의 경력을 갖고 있다시는 군요..
저도 18년 정도 하면 이분 정도의 공력을 갖을 수 있을까..

걱정입니다.. --;
1. Chris Date's Database In Depth from O'Reilly
2. Oracle Concepts manual
3. Expert One-on One: Oracle Written by Tom Kyte
4. Expert Oracle Database Architecture: 9i and 10g Programming Techniques and Solutions
5. Practical Oracle 8i
6. Cost Based Oracle: Fundamentals
7. Optimizing Oracle Performance
8. Oracle Wait Interface: A Practical Guide to Performance Diagnostics and Tuning
 

원문: http://oracledoug.com/books.html

이분이 한국인이 아니기 때문에 당연히 외국 원서 입니다. ㅋ
국내에 번역 된 책도 많이 있는데, 알라딘에서 찾아 링크 좀 걸까 했는데, 국내에서는 절판이나 품절이 많네요.




널리 알려진 기능이지만 사용하는 방법 sample 입니다.
PC 내에 있는 scrpt 정리하다 삭제 전에 한번 올려 봅니다.
혹시 누군가에겐 필요할까 싶어서 ㅎㅎ
(절대 몇일 동안 oracle post가 없어 올리는 건 아닙니다. --;)

ora102@TEST4:/app/oracle/product/db/rdbms/log> sqlplus scott/tiger

SQL*Plus: Release 10.2.0.3.0 - Production on Sun Aug 3 14:57:17 2008

Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.

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

SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
BIN$U4gkooULB1PgQLMKTWwM7A==$0 TABLE
BIN$U4iK63kw1zTgQLMKTWx98g==$0 TABLE
EMP                            TABLE
AAA                            TABLE

SQL>
SQL> show recyclebin
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
EMP              BIN$U4iK63kw1zTgQLMKTWx98g==$0 TABLE        2008-08-03:14:32:03
TEST             BIN$U4gkooULB1PgQLMKTWwM7A==$0 TABLE        2008-08-03:14:03:27

SQL>  FLASHBACK TABLE TEST TO BEFORE DROP;

Flashback complete.

SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
BIN$U4iK63kw1zTgQLMKTWx98g==$0 TABLE
TEST                           TABLE
EMP                            TABLE
AAA                            TABLE

SQL> purge recyclebin;

Recyclebin purged.

SQL> select * from tab;

TNAME                          TABTYPE  CLUSTERID
------------------------------ ------- ----------
TEST                           TABLE
EMP                            TABLE
AAA                            TABLE


SQL> drop table test;

Table dropped.

SQL> select * from user_recyclebin;

OBJECT_NAME                    ORIGINAL_NAME                    OPERATION
------------------------------ -------------------------------- ---------
TYPE                      TS_NAME                        CREATETIME
------------------------- ------------------------------ -------------------
DROPTIME               DROPSCN PARTITION_NAME                   CAN CAN
------------------- ---------- -------------------------------- --- ---
   RELATED BASE_OBJECT PURGE_OBJECT      SPACE
---------- ----------- ------------ ----------
BIN$U4juzy+wgKngQLMKTWwgxQ==$0 TEST                             DROP
TABLE                     USERS                          2008-08-03:13:57:59
2008-08-03:14:59:59   15636802                                  YES YES
     56903       56903        56903   

2010/03/30
oracle flashback 기능을 그림과 함꼐 잘 설명해 놓은 post가 있어 링크 겁니다

행복만땅 개발자 :: [오라클 10g] 플래시백의 설정/관리





oracle RAC(OPS도 마찬가지지만)를 사용할때, 각각의 instance는 자신의 SGA와 buffer cache를 갖는다.

RAC는 성능 향상과 노드간의 데이터 정합성을 위해 이들 각 instance내의 buffer내의 block의 변경을 자알 관리해야 한다. cache resource라 불리는 이들 buffer에 대한 각각의 copy 본은 cluster의 한 노드에는 반드시 master를 갖고 있어야 한다.

10g 이전 버전에서는 한 instance에서 해당 cache resource에 대해 master로 설정되면 instance startup이나 shutdown, node eviction 등으로 인한 reconfiguration 이전에는 그 설정이 지속되게 된다.  따라서 만약 노드 B가 cache resource에 대해 master로 설정되면 reconfiguration이 발생되기 전까지는 이 설정이 지속된다.

2009년 10월 12일 Update:


첨부된 문서는 RAC 간의 데이터 전송인 "cache fusion"에 대한 설명이다. 해당 설명의 그림을 보면 buffer access를 위해 계속 resource master에 해당 block에 대해 어떤 instance에서 master owner ship을 갖고 있는지 확인하고 있다.
이 문서는 2003년 봄 oracle magazine에 실린 "cache fusion"에 대한 설명이다.


10g에서 소개된 DRM은 자주 access 되는 node로의 buffer에 대한 master가 변경되는 re-mastering 개념이 소개되었다. 따라서 이전 버전처럼 reconfiguration 없이도 master의 재 설정이 가능해 졌다.

이러한 re-mastering operation은 LMD trace에서 확인할 수 있다.
Begin DRM(202) - transfer pkey 4294951314 to 0 oscan 1.1
*** 2006-08-01 17:34:54.645
Begin DRM(202) - transfer pkey 4294951315 to 0 oscan 1.1
*** 2006-08-01 17:34:54.646
Begin DRM(202) - transfer pkey 4294951316 to 0 oscan 1.1
*** 2006-08-01 17:34:54.646
Begin DRM(202) - transfer pkey 4294951317 to 0 oscan 1.1
RAC에서는 buffer내의 block에 대한 access시 반드시 해당 block의 master와 통신을 하게 되어 있다. 따라서 특정 노드에서 자주 참조되는 block은 해당 노드에서 master를 갖는것이 성능상의 잇점을 얻을 수 있을 것이다.

하지만 oracle10g RAC에 대해서 이전 버전처럼 업무를 노드 별로 나누는 것을 강조하고 있지 않다. 더구나 sql*net의 load balance 기능을 사용하고 있다면, remastering에 의한 부담이 더 크지 않을까나..

참고 : Note 390483.1 DRM - Dynamic Resource management

2010/03/25 Updated: 
Oracle database internals by Riyaj라는 유명한 오라클 블로그에서 DRM에 대해 post 하나를 올렸군요. 
오 ..역쉬, force가 다르군요. ㅜㅡ

내용을 좀 읽어보니 아예 DRM을 disable 시키지 말고 값을 크게 해서 remastering을 최소화하는 것을 권하는 군요. 
DRM 기능은 _gc_affinity_time을 0으로 설정해 disable 시킬 수 있습니다. 그러나 _gc_affinity_limit와 _gc_affinity_minimum의 값 조정으로 DRM 기능을 최소화 할 수 도 있군요. 이렇게 최소화 시켜놓으면 사용자게 manual 하게 rematering 하는 게 여전히 가능하답니다. 
manual 하게 수정은 "oradebug lkdebug -m pkey" 명령으로 가능합니다. 

자세한 내용은 아래 링크에서...

http://orainternals.wordpress.com/2010/03/25/rac-object-remastering-dynamic-remastering/






Oracle EM grid control에서 특정 event가 발생하면 해당 내용을 Critical, Warning으로 구분해서 alert 발생시킵니다. 
이 alert 내용을 mail로 delivery 할수 있고 user PL/SQL을 이용해 다른 여러 응용도 가능합니다. 

다음의 SQL script는 EM에서 발생한 alert message와 alert의 상태, 그리고 이에 대한 delivery 수행이 잘 되었는지 확인하는 방법입니다. 

* Oracle 11g Release 1에 Oracle Grid conrol 10.2.0.5 환경에서 테스트 되었습니다. 

SQL> select TARGET_NAME||' /'||METRIC_NAME||' /'||KEY_VALUE METRIC_NAME,TIMESTAMP,DELIVERED,substr(b.MESSAGE,1,100) message,ALERT_STATE,substr(b.DELIVERY_MESSAGE,1,50) DELIVERY_MESSAGE
from sysman.mgmt_notification_log a, SYSMAN.MGMT$ALERT_NOTIF_LOG b
where a.SOURCE_OBJ_GUID(+) =b.SOURCE_OBJ_GUID
and to_char(TIMESTAMP,'MMDD') = '0311'
-- and target_name = 'LISTENER_PMGT_FLPEME01'
-- and DELIVERED ='Y'
order by TIMESTAMP
/


METRIC_NAME                              TIMESTAMP      DEL MESSAGE                                            ALERT_STAT DELIVERY_MESSAGE
--------------------------------------- -------------- --- -------------------------------------------------- ---------- --------------------------------------------------
TEST /problemTbsp /TS_TEST                03/11 02:07:51 Y   Tablespace [TS_TEST] is [97 percent ] full           Critical   Called PL/SQL procedure SYSMAN.LOGGING_ALERT
TEST /problemTbsp /TS_TEST                03/11 02:09:22 Y   Tablespace [TS_TEST] is [97 percent ] full           Critical   Called PL/SQL procedure SYSMAN.LOGGING_ALERT
TEST /problemTbsp /UNDOTBS1              03/11 02:57:45 Y   Tablespace [UNDOTBS1] is [97 percent ] full        Critical   Called PL/SQL procedure SYSMAN.LOGGING_ALERT
TEST /problemTbsp /UNDOTBS1              03/11 02:59:16 Y   Tablespace [UNDOTBS1] is [97 percent ] full        Critical   Called PL/SQL procedure SYSMAN.LOGGING_ALERT






일반적인 HOT block에 따른 현상이 널리 알려진게 'cache buffer chains' 등의 buffer chain에 대한 latch 입니다. 

다음의 SQL은 cache buffers chains children latch 중 가장 sleep count가 높은 children latch의 ADDR에 어떤 block들이 달려 있는지 확인해
그 block 중 가장 동시 접근이 많은 block을 찾는 SQL 입니다. 

select * from (
select HLADDR,TS#,FILE#,DBABLK,TCH , CHILD#,GETS,MISSES,SLEEPS
from x$bh x, 
    (select * from (
     select CHILD#  ,ADDR,GETS,MISSES,SLEEPS  from v$latch_children where name = 'cache buffers chains' order by 5 desc
                   ) 
     where rownum < 2 ) y
where x.hladdr = y.addr
order by tch desc
) where rownum < 2
/





Oracle 11g에서 많은 새로운 기능들이 생겼습니다.
그러나 oracle 11g를 설치하면 제일 먼저 눈에 띄는게 OFA 구조가 바뀐거죠. 
(설치 후 alert log를 한참동안 찾아 헤메였다는.. ^^;)

전통적으로 oracle alert log file과 trace file들은 $ORACLE_BASE/admin/$ORACLE_SID/bdump 에 쌓였었죠. 
(아마 8.0 때부터였던가.. 그랬었을 겁니다. 아마 ㅋ)
가끔 bug이나 resource 문제로 $ORACLE_HOME/rdbms/log에 생기기도 했고요. 

Oracle 11g에서는 이 구조가 좀 바뀌었습니다. $ORACLE_BASE 밑에 diag란 directory 밑에 쪼르륵 달려있습니다. 

$ORACLE_BASE/diag/rdbms/'DATABASE NAME'/$ORACLE_SID/trace

이렇게 구조가 달라진 이유는 아마 metalink.oracle.com에서 support.oracle.com으로의 변화와 OCM (oracle configuration management) 때문이지 않을까 싶습니다. 즉, database의 특정 환경, event 들을 OCM을 통해 support.oracle.com에서 지원하려는 .. 뭐 그런 이유 이지 않을까 싶습니다. 

암튼 단순히 trace file과 alert log의 위치만 변경된 것은 아니죠. adrci라는 diag file 관리 tool이 만들어 졌습니다. 
이 tool을 이용해 현재 발생한 problem, incident 등을 쉽게 파악할 수 있으며, 기간이 오래된 trace file 등을 한방에 정리도 할 수 있습니다.
이러한 기능은 EM에서도 가능하고요. 

oracle 내에서 어떤 문제가 생겨 SR을 open해 분석을 진행할때 가장 귀찮은 게 관련 trace, log file을 취합해서 upload하는 겁니다. (저는 그래요.. ㅋ) adrci에서는 관련 trace, log file을 한꺼번에 취합해 주는 기능이 있는데, 이것이 IPS (incident packaging service) 입니다. 

구조가 바뀌고 "PROBLEM"과 "INCIDENT"라는 단어들이 나오는데, Problem은 특정한 문제 전체를, Incident는 문제의 발생 자체를 말합니다. 즉, ORA-1555가 10번 발생했다면 ORA-1555 1개의 문제에 10번의 incident가 발생한게 됩니다.

다음은 ADRCI에서 incident를 packaging 하는 방법입니다. 
그냥 보시면 아실만한 내용이라 별도의 설명은 생략하겠습니다. 

$ adrci

ADRCI: Release 11.1.0.7.0 - Production on Mon Mar 8 16:35:56 2010

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

ADR base = "/oracle"
adrci> 
adrci> show incident

ADR Home = /oracle/diag/rdbms/test/TEST01:
*************************************************************************
INCIDENT_ID          PROBLEM_KEY                                                 CREATE_TIME                              
-------------------- ----------------------------------------------------------- ---------------------------------------- 
656910               ORA 600 [critical problem임]                                2010-01-29 11:31:45.635899 +09:00       
656909               ORA 600 [critical problem임]                                2010-01-29 11:19:30.662164 +09:00       
656478               ORA 7445 [critical problem임]                               2010-01-25 13:21:00.086171 +09:00       
656477               ORA 7445 [critical problem임]                               2010-01-25 13:16:54.434050 +09:00       
               ...
20 rows fetched

ADR Home = /oracle/diag/clients/user_oracle/host_2085451943_11:
*************************************************************************
INCIDENT_ID          PROBLEM_KEY                                                 CREATE_TIME                              
-------------------- ----------------------------------------------------------- ---------------------------------------- 
25                   oci 24550 [3]                                               2009-08-19 17:01:14.504278 +09:00       
17                   oci 24550 [3]                                               2009-08-19 16:59:56.250301 +09:00       
9                    oci 24550 [3]                                               2009-06-18 08:09:28.329766 +09:00       
1                    oci 24550 [3]                                               2009-06-18 08:07:58.791738 +09:00       
4 rows fetched

adrci> show homepath
ADR Homes: 
diag/rdbms/test/TEST01
diag/clients/user_oracle/host_2085451943_11
diag/clients/user_precise/host_2085451943_11
diag/clients/user_norad/host_2085451943_11
diag/tnslsnr/TEST01/test_TEST01
diag/tnslsnr/TEST01/listener_TEST01
diag/tnslsnr/TEST01/listener_TEST01
diag/tnslsnr/TEST01/listener
adrci> set homepath diag/rdbms/test/TEST01
adrci> ips create package incident 656910
Created package 1 based on incident id 656910, correlation level typical
adrci>
adrci> IPS GENERATE PACKAGE 1 in /oracle/diag
Generated package 1 in file /oracle/diag/ORA600critical problem임_20100308163713_COM_1.zip, mode complete
adrci> exit
$ls -altr
total 12744
-rw-r--r--   1 oracle     dba        6456404 Mar  8 16:39 ORA600critical problem임_20100308163713_COM_1.zip

참고: 
Note.738732.1 ADR How to Package Diagnostic Information in 11g





Oracle global temporary table은 Transaction 내에서 임시로 만들 수 있는 table을 지칭합니다. 
transaction 내부에서 사용하는 것이니 당연히 transaction을 commit/ rollback하면 없어지겠죠. 

"global"이라는 단어가 붙은 이유는 table의 구조는 공유한데서 나오니 않았나 싶습니다. 
같은 global temporary table에 각각의 세션에서 데이터를 insert 하면 서로 다른 값을 보여주게 됩니다. 

Global temporary table 생성 명령은 table 생성명령에 global temporary 만 넣어주면 됩니다. 

create global temporary table test_temp ..

global temporary table을 만든 후 dba_objects에서 query를 해보면 해당 이름으로 object_type이 table이라고 나오긴하나, 
dba_segments에서는 해당 이름의 segment는 없는 것으로 보여줍니다. v$sort_usage를 보니 temp tablespace에 temporary data segment type으로 한덩어리 만들어 놓았군요..






오라클의 전체적인 사용현황과 그에 따른 AWR, ADDM을 수행하기 좋은 툴하나 소개합니다. 
OraScope.Net이라는 툴인데, FreeWare 입니다. 

Session, Lock, Database 등 모니터링 기능은 없는 듯하나, 
Database 전체를 파악하기 위한 resource 사용현황들은 거의 다 있는 것 같습니다. 

Download는 아래사이트에 방문하시면 됩니다..

OraScope.Net LITE 는 FREEWARE 입니다.

 

즉, 무료 오라클 성능 모니터링 툴입니다.

개인, 기업, 기관등 사용자와 장소에 구애받지 않고, 마음대로 사용하실수 있습니다.

다만, OraScope.Net LITE 를 저작자의 동의없이 상업적 용도로는 사용할수 없으며,

본 싸이트에서 제공하는 배포화일 형태 그대로, 자유로이 배포하실수 있습니다.(배포화일의 재 PACKAGING은 불허)

 

OraScope.Net LITE 의 모든 저작권은 저작자( orascope@orascope.net ) 에게 있습니다.

 

OraScope.Net LITE 를 사용하여 일어나는 문제나 기타 제반 사항에 대해, 저작자는 책임이 없음을 알려드립니다.

(기타 후원해 주실 분이나 업체는 orascope@orascope.net 로 연락주시면 됩니다.Laughing)









오라클에는 현재 수행 중인 세션을 정리하는 방법이 두가지가 있습니다.

하나는 익히 알고 있는 ALTER SYSTEM KILL SESSION 명령이고 다른 하나는 ALTER SYSTEM DISCONNECT SESSION 명령입니다. 이 두개의 명령은 "ALTER SYSTEM" 명령의 "end_session_clauses"에 속하는 명령입니다.




일반적으로 비정상적인 세션을 정리할 때 alter system kill session 명령을 수행하곤 하는데, kill session 명령은 현재 수행중인 transaction을 바로 정리해 버리죠. 그런데, disconnect session  명령은 현재까지 수행된 transaction은 처리하고 session을 정리할 수 있는 방법입니다.

ALTER SYSTEM KILL SESSION '13, 8' IMMEDIATE;
ALTER SYSTEM DISCONNECT SESSION '13, 8' POST_TRANSACTION;


DISCONNECT SESSION은 dedicated server를 강제로 정리해 현 세션을 disconnect 하게 된다. 세션의 지정은 KILL SESSION 과 마찬가지로 'sid, serial#' 으로 지정한다.

DISCONNECT SESSION 문에는 "POST_TRANSACTION" 과 "IMMEDIATE" option을 지정할 수 있다.

POST_TRANSACTION은 현재 transaction이 수행 중이라면 이 transaction이 끝난 후에 세션을 정리하게 되며, 만약 현재 수행 중인 transaction이 없다면 "KILL SESSION"과 동일한 효과를 갖는다. (근데, "KILL SESSION"절에 IMMEDIATE option은 언제 생긴거람.. ?)









예전 포스트에서 V$ view와 DBA_ view의 차이점에 대해서 언급했었습니다.

v$ view는 memory structure data를 보여주며, dba_ table(?)은 system tablespace 상의 data dictoinary data를 보여줍니다. 10g에서 awr 관련 view들이 만들어져서 dba_hist view 등에서 memory structure statistic data를 system tablespace에 저장해서 보여주기도 하죠.


아래의 v$fixed_view_definition view는 오라클의 fixed view의 description을 보여주는 view 입니다.
아래의 내용은 얼마전 bind 변수 값을 찾을 방법이 없을까 .. 해서 한번 뒤져보느라 query 해본 내용입니다.
역시 그런 방법은 없는 것 같더군요.. --;

SQL> select view_definition from v$fixed_view_definition where view_name = 'GV$SQL_BIND_CAPTURE';

VIEW_DEFINITION
-----------------------------------------------------------------------------------------------------------------------
select INST_ID,                 KQLFBC_PADD,                 KQLFBC_HASH,      
          KQLFBC_SQLID,
KQLFBC_CADD,                 KQLFBC_CHNO,                 substr(KQLFBC_NAME,
1, 30),                 KQLFBC_POS,
          to_number(decode(KQLFBC_DUPPOS, 65535, NULL, KQLFBC_DUPPOS)),        
        KQLFBC_OACDTY,             s
ubstr(KQLFBC_DTYSTR, 1, 15),                 KQLFBC_OACCSI,                
KQLFBC_OACPRE,              KQLFBC_OACSCL
,                 KQLFBC_OACMXL,                 decode(KQLFBC_WCAP, 0, 'NO',
'YES'),                 decode(KQLFBC_WCAP
, 0, to_date(NULL), KQLFBC_LCAP),                 KQLFBC_STRVAL,               
  decode(KQLFBC_WCAP, 0, NULL,
                            sys.sys$rawtoany(KQLFBC_BINVAL, KQLFBC_OACDTY,     
                              KQLFBC
_OACCSF, KQLFBC_OACCSI))          from x$kqlfbc;


* 여기저기서 좋다는 책 몇권 추천합니다. 고수가 되는 그날까지.. 파이팅!!



뻔한 script 지만, 나름 쓸만한 shell script 입니다.
shell로 저장한 후 뒤에 sql script와 interval을 주만 무한 루프..
active session 모니터링용으로는 뭐 GUI tool이 부럽지 않죠.. ㅋ

<사용방법>
rpt <sql script name> <interval(sec)>

<내용>
if [ $# -eq 1 ]
then
 arg2=2
elif [ $# -eq 2 ]
then
 arg2=$2
else
     echo "Usage : rpt sql term";
     exit;
fi

arg1=$1
while true
do
sqlplus -s '/ as sysdba' <<EOF
set linesize 200
set pause off
set pagesize 120
@$arg1
EOF
sleep $arg2
done




Oracle External table은 오라클 외부의 데이터를 내부로 loading해 table 형식으로 보여 줍니다.
Oracle 11g R2에서는 "PREPROCESSOR 절"이 생겨 이 외부 file에 대해 선처리 프로세서를 정의해 줄 수 있습니다.

대부분 외부 SAM file 형식이니 압축해제나 shell을 통한 추출 정도의 선 프로세서를 정의할 수 있겠네요.
잘만 된다면 SAM file 저장하는 공간을 줄일 수 있겠네요.

예 : compress된 데이터를 gunzip을 이용해 압축 해제 후 loading

CREATE TABLE sales_transactions_ext
     (PROD_ID NUMBER, CUST_ID NUMBER, TIME_ID DATE, CHANNEL_ID NUMBER, PROMO_ID NUMBER, QUANTITY_SOLD NUMBER,
      AMOUNT_SOLD NUMBER(10,2), UNIT_COST NUMBER(10,2), UNIT_PRICE NUMBER(10,2))
ORGANIZATION external
 (TYPE oracle_loader DEFAULT DIRECTORY data_file_dir
  ACCESS PARAMETERS
  (RECORDS DELIMITED BY NEWLINE CHARACTERSET US7ASCII
   PREPROCESSOR exec_file_dir:'gunzip' OPTIONS '-c'
   BADFILE log_file_dir:'sh_sales.bad_xt'
   LOGFILE log_file_dir:'sh_sales.log_xt'
   FIELDS TERMINATED BY "|"
   LDRTRIM ( PROD_ID, CUST_ID, TIME_ID DATE(10) "YYYY-MM-DD", CHANNEL_ID, PROMO_ID, QUANTITY_SOLD,
                AMOUNT_SOLD, UNIT_COST, UNIT_PRICE))
location ('sh_sales.dat.gz') )
REJECT LIMIT UNLIMITED;






오라클의 통계정보는 다른 DB나 계정으로 옮겨질 수 있습니다.
개발장비에서 수집된 통계정보를 옮긴다거나, 기존의 운영장비의 통계정보를 migration 할 대상으로 옮겨 동일한 SQL 수행을 유도할 수 있습니다.

다음은 현재 SCOTT 계정의 통계정보를 다른 Database의 SCOTT 계정으로 옮기는 예제입니다.

* statistic 정보 수집 table 생성
SQL> exec dbms_stats.create_stat_table('SCOTT','STATS');

* scott.emp table의 통계정보를 statistic 정보수집 테이블인 STATS로 export
exec dbms_stats.export_table_stats('SCOTT','EMP',NULL,'STATS',NULL,TRUE);

* STATS table export
%exp scott/tiger tables=STATS file=expstat.dmp

* STATS table import
%imp scott/tiger file=expstat.dmp full=y log=implog.txt 

* STATS table의 통계정보를 SCOTT.EMP에 import
exec dbms_stats.import_table_stats('SCOTT','EMP',NULL,'STATS',NULL,TRUE);

기존의 통계정보를 다른 Database의 동일 계정으로 옮기는 작업에 대한 내용들은 많이 기술 되어 있는데,
이름이 다른 계정은 어떻게 옮길까요?

다른 계정으로 통계정보를 옮기는 작업은 다른 데이터베이스내의 동일 계정으로 통계정보를 옮기는 작업처럼 procedure로만은 불가능합니다.
물론 작업 자체가 불가능하다는 이야기는 아닙니다.

You may not export stats from one schema name and import into a different schema name (Bug 1077535). The schema names much match exactly. If the target database schema name (import database) is different from the source database schema name (export database), then you may update the table you exported the statistics into and set the C5 column to the target schema name.

통계정보를 export 받기 전에 생성하는 statistic 정보를 저장하는 stat table에는 통계정보가 만들어진 계정의 이름이 지정되어 있어,
이를 다른 계정으로 import하려고 하면 import는 성공했다고 나오나 통계정보는 입력 되지 않습니다.

따라서 수집된 통계정보가 있는 table의 owner column의 owner를 바꿔줘야 합니다.

i.e.
"update table sd_stat set c5 = '<target schemaname>'
where c5 = '<Source Schema name>'
  and statid = '<Stat Id used while exporting these stats>;"

update sd_stat set c5 = 'JBARLOW';
where c5 = 'SCOTT'
  and statid = 'a';
commit;

정리해 보자면 SCOTT 계정의 SD table의 통계정보를 JBAARLOW 계정으로 옮긴다면 아래와 같이 수행해야 합니다.

* statistic 정보 수집 table 생성
SQL> exec dbms_stats.create_stat_table('SCOTT','SD_STAT');

* scott.sd table의 통계정보를 statistic 정보수집 테이블인 SD_STATS로 export
exec dbms_stats.export_table_stats('SCOTT','SD',NULL,'SD_STAT',NULL,TRUE);

*  SD_STAT table의 계정정보 수정
update sd_stat set c5 = 'JBARLOW';
where c5 = 'SCOTT';
commit;

* STATS table의 통계정보를 JBARLOW.SD table에 import
exec dbms_stats.import_table_stats('JBARLOW','SD',NULL,'SD_STAT',NULL,TRUE,'SCOTT');


참고 : Note 117203.1 How to Use DBMS_STATS to Move Statistics to a Different Database




+ Recent posts