oracle blog(?)에 oracle 11g로 upgrade해야할 이유 6개가 나왔네요. 

오라클 support 기간 종료, security 문제에 대한 fix, 그리고 new feature의 이점들.. 
뭐 훌륭한 feature 들이 많은건 일단 인정.. 
그래도 가장 큰 이유는 support 기간 종료가 아닐까.. 싶네요. 

#1: Oracle support period will end soon or has ended.

#2: The application provider is pushing you to uprgade.

#3: CPU or PSUs - security fixes.

#4: Potential cost savings part 1.

#5: Potential cost savings part 2.

#6: Faster access to LOB data - move to Secure Files.


출처 : Why upgrade?


Oracle 9i에서 소개된 Multitable insert는 한개의 테이블에 여러 row를 넣거나, 여러개의 테이블에 데이터를 한 insert 명령으로 넣을 수 있습니다.  이전 버전에서는 이런 기능은 PL/SQL로 구현을 해야 했으나 9i 이후로는 한 명령으로 수행할 수 있습니다.

INSERT ALL
INTO cust_order (order_nbr, cust_nbr, sales_emp_id,order_dt, expected_ship_dt, status)
VALUES (ord_nbr, cust_nbr, emp_id,ord_dt, ord_dt + 7, status)
INTO cust_order (order_nbr, cust_nbr, sales_emp_id,order_dt, expected_ship_dt, status)
VALUES (ord_nbr + 1, cust_nbr, emp_id,add_months(ord_dt, 1), add_months(ord_dt, 1) + 7, status)
INTO cust_order (order_nbr, cust_nbr, sales_emp_id,order_dt, expected_ship_dt, status)
VALUES (ord_nbr + 2, cust_nbr, emp_id,add_months(ord_dt, 2), add_months(ord_dt, 2) + 7, status)
INTO cust_order (order_nbr, cust_nbr, sales_emp_id,order_dt, expected_ship_dt, status)
VALUES (ord_nbr + 3, cust_nbr, emp_id,add_months(ord_dt, 3), add_months(ord_dt, 3) + 7, status)
INTO cust_order (order_nbr, cust_nbr, sales_emp_id,order_dt, expected_ship_dt, status)
VALUES (ord_nbr + 4, cust_nbr, emp_id,add_months(ord_dt, 4), add_months(ord_dt, 4) + 7, status)
INTO cust_order (order_nbr, cust_nbr, sales_emp_id,order_dt, expected_ship_dt, status)
VALUES (ord_nbr + 5, cust_nbr, emp_id,add_months(ord_dt, 5), add_months(ord_dt, 5) + 7, status)
SELECT 99990 ord_nbr, c.cust_nbr cust_nbr, e.emp_id emp_id,last_day(SYSDATE) ord_dt, 'PENDING' status
FROM customer c CROSS JOIN employee e
WHERE e.fname = 'MARY' and e.lname = 'TURNER'
and c.name = 'Gentech Industries';

INSERT ALL
INTO employee (emp_id, fname, lname, dept_id, hire_date) VALUES (eid, fnm, lnm, did, TRUNC(SYSDATE))
INTO salesperson (salesperson_id, name, primary_region_id) VALUES (eid, fnm || ' ' || lnm, rid)
SELECT 1001 eid, 'JAMES' fnm, 'GOULD' lnm,d.dept_id did, r.region_id rid
 FROM department d, region r
 WHERE d.name = 'SALES' and r.name = 'Southeast US';

위의 예와 같이 대상이 되는 모든 데이터를 같은/다른 테이블에 multi-row의 insert 가 가능하지만 특정 condition에 따라 insert도 가능합니다. 이 경우 INSERT FIRST를 사용하는데 이는 한개의 조건에 만족할 경우 나머지 조건은 skip되어 수행됩니다. 반대로 INSERT ALL의 경우 모든 조건을 판단하게 됩니다. 

INSERT FIRST
 WHEN order_dt < TO_DATE('2001-01-01', 'YYYY-MM-DD') THEN
  INTO cust_order_2000 (order_nbr, cust_nbr, sales_emp_id,sale_price, order_dt)
  VALUES (order_nbr, cust_nbr, sales_emp_id, sale_price, order_dt)
 WHEN order_dt < TO_DATE('2002-01-01', 'YYYY-MM-DD') THEN
  INTO cust_order_2001 (order_nbr, cust_nbr, sales_emp_id,sale_price, order_dt)
  VALUES (order_nbr, cust_nbr, sales_emp_id, sale_price, order_dt)
 WHEN order_dt < TO_DATE('2003-01-01', 'YYYY-MM-DD') THEN
  INTO cust_order_2002 (order_nbr, cust_nbr, sales_emp_id,sale_price, order_dt)
  VALUES (order_nbr, cust_nbr, sales_emp_id, sale_price, order_dt)
SELECT co.order_nbr, co.cust_nbr, co.sales_emp_id,co.sale_price, co.order_dt
 FROM cust_order co
 WHERE co.cancelled_dt IS NULL
 AND co.ship_dt IS NOT NULL;




아래 blog 내용 처럼 v$lock을 조회할때 그리 시간이 많이 걸리는 경험은 없었던것 같지만..
v$lock을 조회하면 내부 fixed table join시 'MERGE JOIN CARTESIAN'이 사용되며 여기에 비용이 많이 든다는 군요.
혹시 v$lock query 결과가 늦으시면 ordered hint를 써보심이...


SQL statement for V$LOCK!!! 
select s.inst_id,l.laddr,l.kaddr,s.ksusenum,r.ksqrsidt,r.ksqrsid1, r.ksqrsid2,l.lmode,l.request,l.ctime,decode(l.lmode,0,0,l.block) from v$_lock l, x$ksuse s, x$ksqrs r where l.saddr=s.addr and concat(USERENV('Instance'),l.raddr)=concat(r.inst_id,r.addr) and s.inst_id = USERENV('Instance'); 




oracle index rebuild를 판단하는 기준이나 rebuild가 필요한지 자체에 대한 많은 말들이 있긴한데.. 

다음의 글은 index_stats view의 del_lf_rows를 이용한 index rebuild 방안에 대한 구조적인 한계에 대한 설명입니다.
뭐 이러한 방안을 대량 delete 작업 후 바로 적용하면 될 거 같은데,
아래와 같은 내용을 알아둬야 .. 수치가 좀 이상하게 나올 경우 당황하지 않겠네요~ 

But, as the Oracle myth busters like Richard Foote have been saying for years,  that's not how Oracle's B-tree indexes work. When you delete an index entry, Oracle marks it as deleted but leaves it in place. When you commit your transaction Oracle does nothing to the index entry – but other processes now know that the entry can be wiped from the block allowing the space to be re-used.      (원문 : Index Rebuilds « Oracle Scratchpad )




alert log file은 오라클 데이터베이스 운영을 위해서는 꼭 확인해야 하는 가장 기본적인 log file이다. 
이 기본적인 alert log file은 이름처럼 꼭 alert을 안줘도 될만한 정보까지도 alerting(?)질을 하곤 하는데, 
online redo log size가 너무 작거나 변경량이 많은 경우 그 내용이 너무 많아 관리자들은 확인에 소홀해 지기도 한다.
하지만 꼭 봐야한다!!  

아래 기술한 내용은 alert log file을 '날짜|로그' format으로 변경해주는 awk 명령이다. 
가끔 장애가 발생하면 연관 서버, 업무들을 시간 순으로 나열할 일이 생기는데 요런 작업을 좀 편하게 해보려고 만들어 봤다.  
추가로 alert log file을 external table을 이용해 DB에 loading 하는 것까지 추가한다. 

1. awk 명령을 이용해 "시간|로그내용"으로 변경하기

+ alert log file

Fri Jul 29 13:40:01 2011
Thread 1 advanced to log sequence 292352
  Current log# 2 seq# 292352 mem# 0: /FS/redo02a.log
  Current log# 2 seq# 292352 mem# 1: /FS/redo02b.log
Thread 1 advanced to log sequence 292353
  Current log# 3 seq# 292353 mem# 0: /FS/redo03a.log
  Current log# 3 seq# 292353 mem# 1: /FS/redo03b.log
Fri Jul 29 13:42:19 2011
Thread 1 advanced to log sequence 292354
  Current log# 4 seq# 292354 mem# 0: /FSredo04a.log
  Current log# 4 seq# 292354 mem# 1: /FSredo04b.log
Fri Jul 29 13:50:01 2011
Thread 1 advanced to log sequence 292355
  Current log# 5 seq# 292355 mem# 0: /FSredo05a.log
  Current log# 5 seq# 292355 mem# 1: /FSredo05b.log
Thread 1 advanced to log sequence 292356
  Current log# 1 seq# 292356 mem# 0: /FSredo01a.log
  Current log# 1 seq# 292356 mem# 1: /FSredo01b.log
Fri Jul 29 13:53:57 2011
Thread 1 advanced to log sequence 292357
  Current log# 2 seq# 292357 mem# 0: /FS/redo02a.log
  Current log# 2 seq# 292357 mem# 1: /FS/redo02b.log

+ awk 명령을 이용해 날짜와 로그 내용을 병합한다. 
 
$ tail -100 /bdump/alert_SID.log | awk '{if (($5=="2011") && $6 =="") {vdate = $0} else {print vdate,"|", $0} }' | grep 2011 > /fs/app/oracle/product/rdbms/log/alert_test.log

$ cat  /fs/app/oracle/product/rdbms/log/alert_test.log
 
Fri Jul 29 13:42:19 2011 | Thread 1 advanced to log sequence 292354
Fri Jul 29 13:42:19 2011 |   Current log# 4 seq# 292354 mem# 0: /FS/redo04a.log
Fri Jul 29 13:42:19 2011 |   Current log# 4 seq# 292354 mem# 1: /FS/redo04b.log
Fri Jul 29 13:50:01 2011 | Thread 1 advanced to log sequence 292355
Fri Jul 29 13:50:01 2011 |   Current log# 5 seq# 292355 mem# 0: /FS/redo05a.log
Fri Jul 29 13:50:01 2011 |   Current log# 5 seq# 292355 mem# 1: /FS/redo05b.log
Fri Jul 29 13:50:01 2011 | Thread 1 advanced to log sequence 292356
Fri Jul 29 13:50:01 2011 |   Current log# 1 seq# 292356 mem# 0: /FS/redo01a.log
Fri Jul 29 13:50:01 2011 |   Current log# 1 seq# 292356 mem# 1: /FS/redo01b.log
Fri Jul 29 13:53:57 2011 | Thread 1 advanced to log sequence 292357
Fri Jul 29 13:53:57 2011 |   Current log# 2 seq# 292357 mem# 0: /FS/redo02a.log
Fri Jul 29 13:53:57 2011 |   Current log# 2 seq# 292357 mem# 1: /FS/redo02b.log
Fri Jul 29 14:00:02 2011 | Thread 1 advanced to log sequence 292358
Fri Jul 29 14:00:02 2011 |   Current log# 3 seq# 292358 mem# 0: /FS/redo03a.log
Fri Jul 29 14:00:02 2011 |   Current log# 3 seq# 292358 mem# 1: /FS/redo03b.log
Fri Jul 29 14:00:02 2011 | Thread 1 advanced to log sequence 292359
Fri Jul 29 14:00:02 2011 |   Current log# 4 seq# 292359 mem# 0: /FS/redo04a.log
Fri Jul 29 14:00:02 2011 |   Current log# 4 seq# 292359 mem# 1: /FS/redo04b.log

2. 변경된 alert log file을 DB로 loading 하기

+ DB내 directory 정보 확인 
SQL> select * from dba_directories;

OWNER                          DIRECTORY_NAME                 DIRECTORY_PATH
------------------------------ ------------------------------ -----------------------------------
SYS                            DATA_PUMP_DIR                  /fs/app/oracle/product/rdbms/log/

+ external table 만들기 
 
SQL> drop table t_alert_log;
SQL> create table t_alert_log (ldate varchar2(25), text_line varchar2(150)) 
 organization external
 (
   type oracle_loader 
   default directory DATA_PUMP_DIR
   ACCESS PARAMETERS 
   ( 
    records delimited by newline 
    fields terminated by '|' 
   ) 
 location ('alert_test.log')); 

+ 입맛대로 query 하기 
 
SQL> select rownum,a.* from t_alert_log a;
 
    ROWNUM LDATE                     TEXT_LINE
---------- ------------------------- ------------------------------------------------------------------------
       386 Fri Jul 29 13:30:17 2011     Current log# 1 seq# 292351 mem# 0: /FS/redo01a.log
       387 Fri Jul 29 13:30:17 2011     Current log# 1 seq# 292351 mem# 1: /FS/redo01b.log
       388 Fri Jul 29 13:40:01 2011   Thread 1 advanced to log sequence 292352
       389 Fri Jul 29 13:40:01 2011     Current log# 2 seq# 292352 mem# 0: /FS/redo02a.log
       390 Fri Jul 29 13:40:01 2011     Current log# 2 seq# 292352 mem# 1: /FS/redo02b.log
       391 Fri Jul 29 13:40:01 2011   Thread 1 advanced to log sequence 292353
       392 Fri Jul 29 13:40:01 2011     Current log# 3 seq# 292353 mem# 0: /FS/redo03a.log
       393 Fri Jul 29 13:40:01 2011     Current log# 3 seq# 292353 mem# 1: /FS/redo03b.log
       394 Fri Jul 29 13:42:19 2011   Thread 1 advanced to log sequence 292354
       395 Fri Jul 29 13:42:19 2011     Current log# 4 seq# 292354 mem# 0: /FS/redo04a.log
       396 Fri Jul 29 13:42:19 2011     Current log# 4 seq# 292354 mem# 1: /FS/redo04b.log

external table의 경우 text file을 loading 한 순서로 보여주므로 log file의 순서대로 보여주게 되나
이 데이터를 다른 table에 옮길경우엔 반드시 rownum을 같이 넘겨여 한다.
안그러면 순서가 뒤죽박죽~ 될 수 있음.  

tar는 지정된 여러 개의 파일들을 아카이브라고 부르는 하나의 파일로 만들거나, 하나의 아카이브 파일에 집적되어 있는 여러 개의 파일을 원래의 형태대로 추출해내는 유닉스 쉘명령어이다.  tar 아카이브 파일에는 어떻게 파일명을 적든상관없지만, tar로 묶었다는 것을 분명히 해주기 위해 ".tar"라는 파일이름 확장자가 붙는다.  tar 아카이브 파일 내에 들어있는 파일들은 압축되는 것이 아니라, 단지 하나의 파일로 모아지는 것뿐이다. 

tar라는 이름은 파일들이 주로 자기테이프에 백업되고, 이따금씩 검색되기도 하던 때로부터 유래하였다. 그러나, 요즘에는 tar 아카이브가 오히려 유닉스 시스템들간에 파일들을 전송하기 위해 좀더 자주 사용되고 있다. 

자주사용되는 조합

1. 압축하기  
tar -cvzf tarfile.tar.gz ./

-c : tar 화일을 생성한다. 
-v : 생성되는 화일 절차를 보여준다. 
-f : backup 화일명을 지정 한다. Default는 "/dev/rmt0"이다. 
-z : gzip에 현재 tar를 넘겨 압축한다. 

2. 퍼미션 유지하며 압축하기 
tar -cvzp tarfile.tar.gz ./

3. 압축풀기
> tar -xvfz tarfile.tar.gz ./

4. 퍼미션 유지하며 압축풀기 #
> tar -xvfzp tarfile.tar.gz ./

5. 내용 보기 및 테스트 #
> tar -tvfz tarfile.tar 
-t : tar화일의 목차를 보여준다. 

6. 업데이트 
> tar -uvfz tarfile.tar reverse.c
tar 화일 끝에 reverse.c가 변경 되었으면 추가 한다. 

$sqlplus / as sysdba

SQL*Plus: Release 10.2.0.3.0 - Production on Tue May 31 10:33:11 2011
Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.

/usr/lib/pa20_64/dld.sl: Unable to find library 'libskgxn2.sl'.
ERROR:
ORA-12547: TNS:lost contact


원본이 RAC인 DB를 copy해서 single로 띄울때 sqlplus를 실행하면 위의 오류가 발생할 수 있다.
이 경우 rac option을 빼주는 작업이 필요하다.

cd $ORACLE_HOME/rdbms/lib
make -f ins_rdbms.mk rac_off
make -f ins_rdbms.mk ioracle
 

Oracle 11g 이후 default user가 엄청나게 많이 생겼습니다. 

Component Name9iR210gR211gR111gR2                            
Oracle Data MiningODM, ODM_MTRDMSYSSYSSYS
Oracle Enterprise ManagerDBSNMP
SYSMAN
DBSNMP
SYSMAN
MGMT_VIEW
DBSNMP
SYSMAN
MGMT_VIEW
DBSNMP
SYSMAN
MGMT_VIEW
Oracle InterMedia/
Oracle Multimedia 
(11gR1)

ORDPLUGINS
ORDSYS

ORDPLUGINS
ORDSYS
SI_INFORMTN_SCHEMA
ORDPLUGINS
ORDSYS
SI_INFORMTN_SCHEMA
ORDDATA
ORDPLUGINS
ORDSYS
SI_INFORMTN_SCHEMA
Oracle OLAPOLAPSYSOLAPSYSOLAPSYSOLAPSYS
Oracle Label SecurityLBACSYSLBACSYSLBACSYSLBACSYS
Oracle SpatialMDSYSMDDATA
MDSYS
MDDATA 
MDSYS
SPATIAL_CSW_ADMIN_USR
SPATIAL_WFS_ADMIN_USR
MDSYS
MDDATA
SPATIAL_CSW_ADMIN_USR
SPATIAL_WFS_ADMIN_USR
SPATIAL_CSW_ADMIN_USR
SPATIAL_WFS_ADMIN_USR
Oracle TextCTXSYSCTXSYSCTXSYSCTXSYS
Oracle XML DatabaseXDBXDBXDBXDB
Oracle Ultra SearchWKSYS
WKPROXY
WKSYS
WKPROXY
WKSYS
WKPROXY
WK_TEST
The WKUSER role and the WKSYS, WK_TEST, WKPROXY schemas have been deprecated.
Oracle Workspace ManagerWMSYSWMSYSWMSYSWMSYS
Oracle Warehouse BuilderNANAOWBSYSOWBSYS
Oracle Rule Manager & Expression FiltrerNAEXFSYSEXFSYS

EXFSYS


성격이 깔끔하신 분들이 어짜피 lock 걸려 있고 password expire 되어 있는 거 보고 
정리하고 싶은 마음이 굴뚝 같겠지만..

일반 유저 drop 하듯이 정리하면 문제가 발생할 수 있으니 신중하셔야 할 것 같습니다. 
아래 참고에도 list-up 했지만 OUTLN user의 경우 drop 하면 DB가 안뜹니다. 
또 다른 제거 가능한 default user 들도 아래 문서들 참조해서 정상적으로 정리하셔야 합니다. 

database default user에 대한 설명과 안전하게 drop하는 방법, 재 생성하는 방법은 아래 노트를 참조하세요. 

참고 : 
설치된 데이터베이스 구성 요소 및 스키마에 대한 정보 (문서 ID 1608310.1)
Unable To Start The Database With OUTLN Schema Dropped ORA-01092& ORA-18008(문서 ID 855104.1)
http://jonathanlewis.wordpress.com/2010/03/11/dropping-outln/
http://abcdba.com/abcdbaserver11gdefaultschema



오라클은 10g 이후로 active session에 대해 history를 특별한 설정없이 기본적으로 저장합니다. ASH는 v$active_session_history, dba_hist_active_sess_history 두가지 view를 통해 조회할 수 있으며 v$active_session_history는 shared pool내의 ASH 영역에 저장되어 1초 간격의 sampling 데이터입니다. 

dba_hist_active_sess_history 값은 ASH 영역의 active session 정보를 10초 간격으로 sampling 해서 disk로 저장된 정보입니다. 

아래 소개하는 ashdump는 현 시점으로 부터 분 단위의 정보를 sql loader format으로 user dump directory에 저장하게 됩니다. 즉, 문제 시점의 active session 정보를 빠르게 수집할 수 있습니다. 

Command would be like below: where level means minute. lets dump for 10 minutes history

1. SQL> alter session set events 'immediate trace name ashdump level 10'; 
or 
2. SQL> alter system set events 'immediate trace name ashdump level 10'; 
or 
3. SQL> oradebug setmypid 
    SQL> oradebug dump ashdump 10;

수집된 ash file은 Oracle home 밑의 rdbms/demo/ashldr.ctl 파일 통해 sql loader로 DB에 저장할 수 있습니다. 

2594829169,1,161390,"07-18-2003 16:05:21.098717000",13,1,0,"",65535,0,0,2,0,0,0,4294967295,0,0,2,35,100,0,0,10 
05855,0,"oracle@usunrat21 (MMNL)","","",""



참고: 
10g and above Active Session History (Ash) And Analysis Of Ash Online And Offline (Doc ID 243132.1)
http://www.oracle.com/technetwork/database/manageability/ppt-active-session-history-129612.pdf



crs resource의 상태를 crs_stat 명령으로 확인해 보면 가끔 resource의 상태가 UNKNOW인 경우가 가끔 발생한다.
CRS resource가 정상적으로 가동 되지 않은 경우도 있고 또 정상적으로 가동된 것 같은데 UNKNOW인 경우도 가끔 있다.  

oracle CRS resource가 UNKNOWN 상태로 변경되는 이유는 일반적으로 CRS resource start/stop/check 시의 action script 수행이 실패할 때 status가 변경되게 된다. 다음은 CRS resource의 state가 UNKNOWN으로 변경되는 일반적인 원인이다.
    

1.  The permission of the resource trace file is incorrect.
2.  The permission of the action script and other racg script is incorrect.
3.  The server load is very heavy and the action script times out.
4.  The look up to NIS hangs or takes very long time and causes the action script to time out.


CRS resource의 action script는 다음의 명령으로 확인할 수 있다. 
crs_stat -p <resource name such as ora.node1.vip> | grep ACTION_SCRIPT

CRS resource 이름은 다음의 명령으로 확인할 수 있다.
crs_stat | grep -i name

다음은 위에 기술한 CRS resource의 UNKNOWN state의 일반적인 원인에 대해 점검해 볼 항목이다.

1.  The permission of the resource trace file if it is incorrect. 
The resource trace file in in the HOME/log/<node name>/racg directory where HOME is the the HOME directory of action script for the resource.

2.  The permission of racg scripts in the HOME/bin directory if it they are incorrect. 
HOME is the the HOME directory of action script for the resource. Please issue "ls -l HOME/bin/racg*" to get the permission of the racg script. Please issue "ls -l HOME/bin/racg*" as user oracle or a user who normally starts up failing resources.
If any of the racg script is a soft link to another file, then check the permission of the file to which the racg script is soft linked.

3.  Check crsd.log and see if the resource action script timed out. 
If it did, then check if the server load was heavy (95% used or higher) for a minute or longer at the time of the failure. Setting up OSWatcher or IPD/OS can help troubleshooting this if the timeout occurs intermittently. Also, check if the NIC was having a problem at the time of the failure. 


참고 : Common Causes for CRS Resources in UNKNOWN State (Doc ID 860441.1) 

요즘 디스크 가격이 싸져서 C driver 공간 부족할 일은 별로 없겠지만..
가끔 큰 파일들 옮길때 파일 사이즈 만큼의 공간이 C driver에 필요하더군요.

디스크 정리해도 별로 공간이 많이 안남는 다면
가상메모리 공간을 D driver로 옮기시면 어느정도 공간을 확보할 수 있습니다.

내컴퓨터>시스템 등록정보 : 고급 > 성능 : 설정 > 성능옵션 : 고급 > 가상메모리 : 변경 
1. C driver 선택 : 페이징 파일 없음 선택 후 설정 
2. D driver 선택 : 사용자 지정크기(처음크기, 최대크기) 지정 후 설정.
3. reboot

 

오라클 11G R2 이전 버전에서는 BUG으로 인해 v$SQL_BIND_CAPTURE에서 TIMESTAMP 형태의 bind 값이 NULL로 보입니다. 그러나 ANYDATA.AccessTimestamp(value_anydata) 를 이용해 볼수 있는 workaround 가 있군요.

참고: V$SQL_BIND_CAPTURE Does Not Show The Value For Binds Of Type TIMESTAMP (Doc ID 444551.1)

SQL> declare 
bindts timestamp; 
begin 
bindts := systimestamp(); 
execute immediate 'select /* BIND_CAPTURE_TEST */ 1 from dual where :b1 is 
not null' using bindts; 
execute immediate 'select /* BIND_CAPTURE_TEST */ 1 from dual where :b1 is 
not null' using bindts; 
execute immediate 'select /* BIND_CAPTURE_TEST */ 1 from dual where :b1 is 
not null' using bindts; 
end; 


PL/SQL procedure successfully completed. 

SQL> select sql_id from v$sql where sql_fulltext like '%BIND_CAPTURE_TEST%' 
and sql_fulltext not like '%xxx%' and command_type = 3; 

SQL_ID 
------------- 
1mf1ch9vsr06a 

SQL> select name, position, datatype_string, was_captured, value_string, 
anydata.accesstimestamp(value_anydata) from v$sql_bind_capture where sql_id = 
'1mf1ch9vsr06a'; 

NAME POSITION DATATYPE_STRING WAS 
------------------------------ ---------- --------------- --- 
VALUE_STRING 
------------------------------------------------------------------------------ 
-- 
ANYDATA.ACCESSTIMESTAMP(VALUE_ANYDATA) 
--------------------------------------------------------------------------- 
:B1 1 TIMESTAMP YES 
05-JUL-07 12.20.23.311417000 PM


1. program 내 모듈명, 수행 단계별 Action 명 정의 

+ Module, Action 정의 
SQL> exec dbms_application_info.set_module('Module_name','Action');

+ 단계별 Action 정의 
SQL> exec dbms_application_info.set_action('select member table..');
select ...
SQL> exec dbms_application_info.set_action('update member table');
update ...

11g이전 버전에서는 SQL_TRACE, 10046 등의 event는 session이나 instance level로만 설정할 수 있었습니다. 
특정 SQL에 대한 dump를 수행하려면 해당 SQL을 수행하는 세션이나 program을 찾아서 
sqlplus나 oradebug 등을 통해 sql_trace, 10046 event 를 걸어야 했죠. 

다음의 SQL_ID에 대해 event 거는 방안은 sql monitoring에 대단히 유용해 보이네요. 

1. SQL_ID 찾기
SQL> select sql_id,sql_text from v$sql where sql_text like 'select /*+ test */%';
SQL_ID               SQL_TEXT
----------------  ----------------------------------------------- 
6vnyysxnuud8b   select /*+ test */ * from scott.emp

2. 해당 SQL_ID에 sql_trace event 걸기 
SQL> alter session set events 'sql_trace [sql:sql_id=6vnyysxnuud8b]';
Session altered.

3. SQL 수행 
SQL> select * from scott.dept;
SQL> select * from scott.emp;
SQL> select /*+ test */ * from scott.emp;

*** 2011-01-27 13:03:14.561
*** SESSION ID:(10979.4995) 2011-01-27 13:03:14.561
*** CLIENT ID:() 2011-01-27 13:03:14.561
*** SERVICE NAME:(SYS$USERS) 2011-01-27 13:03:14.561
*** MODULE NAME:(SQL*Plus) 2011-01-27 13:03:14.561
*** ACTION NAME:() 2011-01-27 13:03:14.561

=====================
PARSING IN CURSOR #5 len=97 dep=1 uid=0 oct=3 lid=0 tim=5959428212907 hv=2759248297 ad='c0000000c0ee11a8' sqlid='aa35g82k7dkd9'
select binaryDefVal, length(binaryDefVal) from ecol$           where tabobj# = :1 and colnum = :2
END OF STMT
PARSE #5:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=0,tim=5959428212907
EXEC #5:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=2830718548,tim=5959428244106
FETCH #5:c=0,e=0,p=0,cr=2,cu=0,mis=0,r=1,dep=1,og=4,plh=2830718548,tim=5959428244106
STAT #5 id=1 cnt=1 pid=0 pos=1 obj=123 op='TABLE ACCESS BY INDEX ROWID ECOL$ (cr=2 pr=0 pw=0 time=0 us cost=1 size=2028 card=1)'
STAT #5 id=2 cnt=1 pid=1 pos=1 obj=126 op='INDEX RANGE SCAN ECOL_IX1 (cr=1 pr=0 pw=0 time=0 us cost=1 size=0 card=1)'
CLOSE #5:c=0,e=0,dep=1,type=3,tim=5959428244106
=====================
PARSING IN CURSOR #2 len=35 dep=0 uid=5 oct=3 lid=5 tim=5959428244106 hv=1772958987 ad='c0000000c0ed2e48' sqlid='6vnyysxnuud8b'
select /*+ test */ * from scott.emp
END OF STMT
EXEC #2:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=2872589290,tim=5959428244106
FETCH #2:c=0,e=0,p=0,cr=5,cu=0,mis=0,r=1,dep=0,og=1,plh=2872589290,tim=5959428244106
FETCH #2:c=0,e=0,p=0,cr=1,cu=0,mis=0,r=15,dep=0,og=1,plh=2872589290,tim=5959428244106
FETCH #2:c=0,e=0,p=0,cr=3,cu=0,mis=0,r=12,dep=0,og=1,plh=2872589290,tim=5959428244106
STAT #2 id=1 cnt=28 pid=0 pos=1 obj=36463 op='TABLE ACCESS FULL EMP (cr=9 pr=0 pw=0 time=0 us cost=3 size=39673 card=409)'

*** 2011-01-27 13:03:25.877
CLOSE #2:c=0,e=0,dep=0,type=0,tim=5959439294741

> tkprof TEST_ora_17091.trc TEST_ora_17091.out explain=scott/tiger sys=no
TKPROF: Release 11.1.0.7.0 - Production on Thu Jan 27 13:05:37 2011
Copyright (c) 1982, 2007, Oracle.  All rights reserved.

TKPROF: Release 11.1.0.7.0 - Production on Thu Jan 27 13:05:37 2011
Copyright (c) 1982, 2007, Oracle.  All rights reserved.

Trace file: TEST_ora_17091.trc
Sort options: default

********************************************************************************
count    = number of times OCI procedure was executed
cpu      = cpu time in seconds executing 
elapsed  = elapsed time in seconds executing
disk     = number of physical reads of buffers from disk
query    = number of buffers gotten for consistent read
current  = number of buffers gotten in current mode (usually for update)
rows     = number of rows processed by the fetch or execute call
********************************************************************************

SQL ID: 6vnyysxnuud8b
Plan Hash: 2872589290
select /*+ test */ * 
from
 scott.emp

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        0      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        3      0.00       0.00          0          9          0          28
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0          9          0          28

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 5  (SYSTEM)

Rows     Row Source Operation
-------  ---------------------------------------------------
     28  TABLE ACCESS FULL EMP (cr=9 pr=0 pw=0 time=0 us cost=3 size=39673 card=409)

Rows     Execution Plan
-------  ---------------------------------------------------
      0  SELECT STATEMENT   MODE: ALL_ROWS
     28   TABLE ACCESS (FULL) OF 'EMP' (TABLE)

********************************************************************************

OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        0      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        3      0.00       0.00          0          9          0          28
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.00       0.00          0          9          0          28

Misses in library cache during parse: 0

OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.00       0.00          0          2          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.00       0.00          0          2          0           1

Misses in library cache during parse: 1
Misses in library cache during execute: 1

    1  user  SQL statements in session.
    1  internal SQL statements in session.
    2  SQL statements in session.
    1  statement EXPLAINed in this session.
********************************************************************************
Trace file: TEST_ora_17091.trc
Trace file compatibility: 11.1.0.7
Sort options: default

       1  session in tracefile.
       1  user  SQL statements in trace file.
       1  internal SQL statements in trace file.
       2  SQL statements in trace file.
       2  unique SQL statements in trace file.
       1  SQL statements EXPLAINed using schema:
           SCOTT.prof$plan_table
             Default table was used.
             Table was created.
             Table was dropped.
      44  lines in trace file.
       0  elapsed seconds in trace file.




Oracle EM gridcontrol 관련 log file들. 
EM은 어려워~ 

Log / Trace files Generated during the OMS Startup

When any of the above methods are used for the OMS startup, the log/trace files will get generated in the following directories:

1.  <OMS_HOME>/opmn/log: These log files contain the entries for the execution and usage of the OPMN and OPMN-managed processes. The files are described below:

Log file name Description
ipm.log Tracks command execution and operation progress of the Process Monitor (PM) portion of the OPMN
ons.log Tracks the execution of the ONS portion of OPMN which is initialized before PM and hence is useful for early OPMN errors.
OC4J~home~default_island~1 Tracks the startup and shutdown of the OC4J home application server component.
HTTP_Server~1 Tracks the startup and shutdown of the HTTP_Server application server component.
OC4J~OC4J_EM~default_island~1 Tracks the startup and shutdown of the OC4J_EM (OMS) application server component.
OC4J~OC4J_EMPROV~default_island~1 Tracks the startup and shutdown of the OC4J_EMPROV application server component.
OC4J~OCMRepeater~default_island~1 Tracks the startup and shutdown of the OCMRepeater application server component.
WebCache~WebCache~1 Tracks the startup and shutdown of the WebCache  application server component.
WebCache~WebCacheAdmin~1 Tracks the startup and shutdown of the WebCacheAdmin application server component.
opmn.log Contains output generated by OPMN when the ipm.log and ons.log files are not available.
service.log (on Microsoft Windows only). The service.log displays any error messages generated by OPMN services while interacting with service control manager.


2.  <OMS_HOME>/sysman/log: contains the log / trace entries generated during the OMS startup. This will include the details for the repository connection issues. The files updated at startup time are:

Log / Trace file name Description
emctl.log Tracks log messages from the emctl utility.
emoms.log Log messages from the OMS application. By default, the maximum size is set to 20MB after which the file is rotated.
emoms.trc Trace messages from the OMS application. By default, the maximum size is set to 5MB with an index of 10, for file rotation.


For details about troubleshooting the OMS Process Control, refer to:

Note 730308.1: How to Troubleshoot Process Control (start, stop, check status) the 10g Oracle Management Service(OMS) Component in 10 Enterprise Manager Grid Control

참고:
How to Process Control (start, stop, check status) the 10g Oracle Management Service(OMS)? (Doc ID 298991.1)
Master Note for 10g Grid Control OMS Performance Issues (Doc ID 1161003.1)



시스템을 운영하면 가끔 특정 프로세스가 CPU를 점유해서 다른 프로세스에 영향을 끼치곤 합니다. 
이런 경우 kill -9 <process id>로 해당 프로세스를 정리하면 문제가 해결되곤 하죠. 
물론 CPU를 99%를 소모하는 프로세스는 거의 정상적이지 않은 프로세스이므로 kill 하는 게 맞지만, 
가끔 특정 batch 작업 등 많은 시간동안 수행되어 kill 시키기 아까운 프로세스들도 존재합니다. 

아래의 아이디어는 자원을 많이 먹는 프로세스를 kill 명령으로 죽이지 않고 잠시 멈춰두는 방법입니다. 

If that oracle process uses high CPU%, and don't want to kill it yet. we may use "oradebug" to suspend it.

$ ps -e -o pcpu,user,pid,args | sort -k 1 | grep 2904
62.8 oracle 2904 oracleorcl (LOCAL=NO)

SQL> oradebug suspend
Statement processed.

$ ps -e -o pcpu,user,pid,args | sort -k 1 | grep 2904
6.0 oracle 2904 oracleorcl (LOCAL=NO)

참고: http://surachartopun.com/2011/01/oradebug-man.html

물론 kill 명령도 signum (24/26)을 주면 동일하게 suspend를 시킬 수 있습니다. 


   signum   signame   Name            Description
   ___________________________________________________________________________
      0     SIGNULL   Null            Check access to pid
      1     SIGHUP    Hangup          Terminate; can be trapped
      2     SIGINT    Interrupt       Terminate; can be trapped
      3     SIGQUIT   Quit            Terminate with core dump; can be trapped
      9     SIGKILL   Kill            Forced termination; cannot be trapped
     15     SIGTERM   Terminate       Terminate; can be trapped
     24     SIGSTOP   Stop            Pause the process; cannot be trapped
     25     SIGTSTP   Terminal stop   Pause the process; can be trapped
     26     SIGCONT   Continue        Run a stopped process

이런 기능을 운영 서버에 사용하시려면 먼저 정상적으로 수행되는지는 테스트 해봐야 겠죠? 
대부분 요런 기능은 hang 같은 테스트 환경 만들 때 주로 쓰긴 합니다..만 알아서 하시길... ^^;

P.S. 
OS kill 명령에 의한 stop과 oradebug를 이용한 suspend의 차이는 뭘까요? 
suspend 된 세션은 v$session 등에서 어떤 상태로 보여질까요? 



간단히 UTL_FILE을 이용한 scott.emp 테이블 데이터 unloading 하기
create or replace procedure utl_file_test_write (
  filename   in varchar2
  )
is
   v_file            UTL_FILE.FILE_TYPE;
   v_text            VARCHAR2 (20);
   v_filename        VARCHAR2 (200);
   v_delimitedchar   CHAR (1);
BEGIN
   v_delimitedchar := CHR (124);
   v_file := UTL_FILE.FOPEN ('DATA_PUMP_DIR', filename, 'W');
   FOR rec IN
      (SELECT   empno,ename,job,mgr,hiredate,sal,comm,deptno FROM scott.emp)
   LOOP
      UTL_FILE.PUT_LINE (v_file,rec.empno|| v_delimitedchar|| rec.ename||v_delimitedchar|| 
                         rec.job||v_delimitedchar|| rec.mgr||v_delimitedchar||rec.hiredate||
                         v_delimitedchar|| rec.sal ||v_delimitedchar|| rec.comm|| v_delimitedchar|| 
                         rec.deptno  );
   END LOOP; 
   UTL_FILE.FCLOSE (v_file);
END;
/

수행 및 결과
SQL> exec utl_file_test_write ('TEST01');
SQL> !cat /oracle_home/TEST01
7369|SMITH|CLERK|7902|1980-12-17|800||20
7499|ALLEN|SALESMAN|7698|1981-02-20|1600|300|30
7521|WARD|SALESMAN|7698|1981-02-22|1250|500|30
7566|JONES|MANAGER|7839|1981-04-02|2975||20
7654|MARTIN|SALESMAN|7698|1981-09-28|1250|1400|30
7698|BLAKE|MANAGER|7839|1981-05-01|2850||30
7782|CLARK|MANAGER|7839|1981-06-09|2450||10
7788|SCOTT|ANALYST|7566|1982-12-09|3000||20
7839|KING|PRESIDENT||1981-11-17|5000||10
7844|TURNER|SALESMAN|7698|1981-09-08|1500|0|30
7876|ADAMS|CLERK|7788|1983-01-12|1100||20
7900|JAMES|CLERK|7698|1981-12-03|950||30
7902|FORD|ANALYST|7566|1981-12-03|3000||20


블로그 구경다니다가 11g에서 쓸만한 hint 하나 확인해서 공유합니다. 
구구절절한 설명 보다 아래의 예를 보는게 가장 이해하기 쉽겠네요. 


However, Oracle11g allows us to use the IGNORE_ROW_ON_DUPKEY_INDEX hint, which will silently deal with the unique constraint violation errors by simply ignoring and not inserting any row in which the unique values already exist in the table.



SQL> insert into radiohead select rownum, 'OK COMPUTER' from dual connect by level <= 12;
insert into radiohead select rownum, 'OK COMPUTER' from dual connect by level <= 12
*
ERROR at line 1:
ORA-00001: unique constraint (BOWIE.RADIOHEAD_PK_I) violated

SQL> insert /*+ ignore_row_on_dupkey_index(radiohead,radiohead_pk_i) */ into radiohead select rownum, 
'OK COMPUTER' from dual connect by level <= 12;
2 rows created.

SQL> commit;
Commit complete.

위의 예를 보면 알겠지만 unique key 값이 없는 row에 대해서만 insert가 발생합니다. 에러는 생략되고요.. 
즉 새로 입력되는 값이 기존의 unique 값과 constraint violation이 발생한다면 무시되는 거죠.. 

이 hint는 update에는 사용할 수 없습니다. 또 parallel DML과 APPEND mode일 경우에는 무시됩니다. 
몇몇 요구사항에 맞지 않는다면 ORA-38912, ORA-38915, ORA-38913이 발생합니다. 

자세한 내용은 아래 메뉴얼에서...

interval partition을 drop할 때 ORA-14758 에러가 발생하는 군요. 
메세지로만 봐서는 마지막 partition은 drop될 수 없다라는데...
분명 마지막 range의 partition도 아니고.

아래 노트를 보면 명확히 설명되어 있네요. 
마지막 partition이라는 게 처음 table을 생성할 때 만들어진 마지막 partition이며 
이후 DB에서 자동으로 interval partition을 만들때 이 partition을 참조하기 때문에 삭제하면 안된답니다. 

그럼 처음 interval partition을 만들때 마지막 partition은 안지워지니까 
주기적인 데이터 삭제용도로 사용하시려면 마지막 partition의 range에 대해 고려를 좀 해보셔야 겠죠? 

ORA-14758: Last Partition In The Range Section Cannot Be Dropped (Doc ID 882681.1)

Symptoms

You drop a partition and receive the following error:
ORA-14758: Last partition in the range section cannot be dropped

Cause

In case of interval partitioning the partitions which are created automatically depends on the last partition created as a reference while creating a table. So the last partition can not be dropped.

Example:

create table test.orders
(order_id number(12),
order_date date
)
partition by range(order_date)
interval(numtoyminterval(1, 'month'))
(partition p1 values less than (to_date('2000-01-01', 'YYYY-MM-DD')),
partition p2 values less than (to_date('2000-04-01', 'YYYY-MM-DD')),
partition p3 values less than (to_date('2000-07-01', 'YYYY-MM-DD')));

insert into test.orders values(1, to_date('2000-02-15', 'YYYY-MM-DD')) ;
insert into test.orders values(1, to_date('2000-03-15', 'YYYY-MM-DD')) ;
insert into test.orders values(1, to_date('2000-05-15', 'YYYY-MM-DD')) ;
insert into test.orders values(1, to_date('2000-06-15', 'YYYY-MM-DD')) ;
insert into test.orders values(1, to_date('2000-08-15', 'YYYY-MM-DD')) ;
insert into test.orders values(1, to_date('2000-09-15', 'YYYY-MM-DD')) ;

commit;

SQL> select table_name,partition_name,high_value from dba_tab_partitions where table_name='ORDERS';

TABLE_NAME PARTITION_NAME HIGH_VALUE
------------------------------ ------------------------------ --------------------------------------------------------------------------------
ORDERS P1 TO_DATE(' 2000-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P2 TO_DATE(' 2000-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS P3 TO_DATE(' 2000-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS SYS_P115 TO_DATE(' 2000-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
ORDERS SYS_P116 TO_DATE(' 2000-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA

SQL> alter table test.orders drop partition SYS_P116;

Table altered.

SQL> alter table test.orders drop partition P2;

Table altered.

SQL> alter table test.orders drop partition P3;
alter table test.orders drop partition P3
*
ERROR at line 1:
ORA-14758: Last partition in the range section cannot be dropped

Solution

This is expected behaviour.
Do not drop the last partition on which the interval partitions are based.

오류에 대해 좀 찾아 보니 interval을 임시로 바꿔 지우는 방법이 나와 있습니다. 
하지만 오라클쪽 자료(metalink)에는 그런 내용은 없는 것 같습니다. 
요 방법 써도 괜찮을라나? 


임시 테이블은 사용자가 DML(update, insert, delete) 문을 실행한 후, 트랜젝션을 종료(commit)하면 변경된 데이터들이 테이블에 저장되지 않는 테이블이다. 어떤 응용을 개발할 때 데이터를 잠시 저장하는 변수와 같은 유형이다.

temporary table은 특정 session 또는 transaction 동안만 data를 저장한다. 

on commit delete rows : 
트랜젝션을 발생시킨 후, commit문을 실행할 때 없어지는 방법. 한 transaction 동안만 data를 저장(default임)

on commit preserve rows : 
트랜젝션을 종료하면(commit) 테이블 내에 데이터가 저장되었다가 세션을 종료하면 임시 테이블에 저장되었던 데이터들이 모두 없어지는 방법. 한 session 동안만 data를 저장

temporary table은 다음과 같은 성격을 갖는다. 

TABLE의 definition 정보는 data dictionary에 영구적으로 저장되지만, data는 일시적으로 저장된다.
CREATE로 TABLE 생성시 SEGMENT가 할당되는 것이 아니라 첫 번째 INSERT시 할당된다.
DML 작업시 해당 data에 대해 LOCK을 걸지 않는다.
data 변경시 redo log에 기록이 남지 않는다.

다음은 간단한 테스트 이다. 

1. global temporary table 생성 

SQL> create global temporary table gtt ( x int );

Table created.

2. object 생성 확인 

SQL> select dbms_metadata.get_ddl( 'TABLE', 'GTT' ) from dual;

DBMS_METADATA.GET_DDL('TABLE','GTT')
--------------------------------------------------------------------------------
  CREATE GLOBAL TEMPORARY TABLE "SCOTT"."GTT"
   (    "X" NUMBER(*,0)
   ) ON COMMIT DELETE ROWS

SQL> select object_name,object_type from user_objects where object_name = 'GTT';

OBJECT_NAME                    OBJECT_TYPE
------------------------------ ------------
GTT                            TABLE

SQL> select table_name from user_tables where table_name = 'GTT';

TABLE_NAME
------------
GTT

SQL> select table_name,temporary,duration from user_tables where table_name = 'GTT';

TABLE_NAME           TEM DURATION
-------------------- --- ---------------------------------------------
GTT                  Y   SYS$TRANSACTION

SQL> select segment_name from user_segments where segment_name = 'GTT';

no rows selected

SQL> drop table gtt;

Table dropped.

3. global temporary table 생성 

SQL> create global temporary table gtt ( x int ) on commit preserve rows;

Table created.

4. object 생성 확인 

SQL> select dbms_metadata.get_ddl( 'TABLE', 'GTT' ) from dual;

DBMS_METADATA.GET_DDL('TABLE','GTT')
--------------------------------------------------------------------------------
  CREATE GLOBAL TEMPORARY TABLE "SCOTT"."GTT"
   (    "X" NUMBER(*,0)
   ) ON COMMIT PRESERVE ROWS


SQL> select object_name,object_type from user_objects where object_name = 'GTT';

OBJECT_NAME                    OBJECT_TYPE
------------------------------ ------------- 
GTT                            TABLE

SQL> select table_name from user_tables where table_name = 'GTT';

TABLE_NAME
-------------------- 
GTT

SQL> select table_name,temporary,duration from user_tables where table_name = 'GTT';

TABLE_NAME           TEM DURATION
-------------------- --- ---------------------------------------------
GTT                  Y   SYS$SESSION

SQL> select segment_name from user_segments where segment_name = 'GTT';

no rows selected

SQL> drop table gtt;

Table dropped.



> netstat -an | grep 1521 

LISTEN       : 호스트가 임의의 원격지로부터 연결요구를 기다리는 상태
SYN-SENT     : 호스트는 연결 요구를 보내고 완전 이중통신 방식의 연결을 완료하여 답변을 기다리는 상태
SYN-RECEIVED : 호스트는 세션 연결 요구를 기다리는 상태
ESTABLISHED  : 두호스트간의 세션 연결이 성립되어 데이터 전송에 사용이 되는 상태
FIN-WAIT1    : 호스트가 원격지 호스트로부터 연결 종료 요구나 더 일찍 보내졌던 연결 종료 요구의 승인중 하나를 기다리는 상태
FIN-WAIT2    : 호스트가 원격지 호스트로부터 연결 종료 요구를 기다리는 상태
CLOSE-WAIT   : TCP 연결이 상위 레벨 응용프로그램으로 부터 연결 종료를 기다리는 상태
CLOSING      : 호스트가 원격지 호스트로부터 연결 종료 요구 승인을 기다리는 상태
LAST-ACK     : 호스트가 이미 원격지 호스트에 보내진 연결 종료 요구의 승인을 기다리는 상태
TIME-WAIT    : 호스트가 원격지 호스트의 연결 종료 요구의 승인을 수신했음을 보장하기 위해서 충분한 시간을 기다리는 상태
CLOSED       : 두 호스트간에 어떤 연결도 존재하지 않는 상태



* Veritas VCS log 확인 
cat /var/adm/syslog.log | egrep 'Nov 27 00|NOV 27 01' | egrep 'VCS|oracle' | grep -v tty
* strace / tusc / truss 사용
Linux: strace -o /tmp/truss.out -aef sqlplus "/ as sysdba"
HP: tusc -afpo /tmp/truss.out -aef sqlplus "/ as sysdba"
AIX/ Solaris: truss -aefo (output file) (executable)

* OS system log file & error messages
SOLARIS : 
System log file /var/adm/messages

HP : 
System log file /var/adm/syslog/syslog.log
Display system/error messages /usr/sbin/dmesg

Linux :
System log file /var/log/messages
Display system/error messages dmesg
  
AIX :
System log file /var/adm/ras/errlog   
Display system/error messages /bin/errpt -a  

WINDOWS :
Event viewer. click on actions >> export list

HOT backup mode에서 왜 redo log에 추가 정보가 쓰일까요? 
ALTER DATABASE BEGIN BACKUP과 ALTER TABLESPACE BEGIN BACKUP의 차이는? 

아래 두개의 POST에 모든 답이 있네요.. 

Why is excessive redo generated during an Online/Hot Backup

There is not excessive redo generated, there is additional information logged into the online redo log during a hot backup the first time a block is modified in a tablespace that is in hot backup mode.  

in hot backup mode only 2 things are different:

o the first time a block is changed in a datafile that is in hot backup mode, the ENTIRE BLOCK is written to the redo log files, not just the changed bytes.  Normally only the changed bytes (a redo vector) is written. In hot backup mode, the entire block is logged the FIRST TIME.  This is because you can get into a situation where the process copying the datafile and DBWR are working on the same block simultaneously.  Lets say they are and the OS blocking read factor is 512bytes (the OS reads 512 bytes from disk at a time).

The backup program goes to read an 8k Oracle block.  The OS gives it 4k.  Meanwhile -- DBWR has asked to rewrite this block.  the OS schedules the DBWR write to occur right now.  The entire 8k block is rewritten.  The backup program starts running again (multi-tasking OS here) and reads the last 4k of the block.  The backup program has now gotten an impossible block -- the head and tail are from two points in time.  We cannot deal with that during recovery.  Hence, we log the entire block image so that during recovery, this block is totally rewritten from redo and is consistent with itself at least.  We can recover it from there.

o the datafile headers which contain the SCN of the last completed checkpoint are NOT updated while a file is in hot backup mode.  This lets the recovery process understand what archive redo log files might be needed to fully recover this file.

Why is excessive redo generated during an Online/Hot Backup

What about ALTER DATABASE BEGIN BACKUP ?
That command put all database tablespaces in backup mode at the same time. As seen previously, it is a bad idea to put all tablespaces in backup mode, as it is better to do it one by one in order to minimize the supplemental redo logging overhead. Oracle introduces this ‘shortcut’ for one reason only: when doing backup with a mirror split (BCV, Flashcopy, etc), the copy gets all the datafiles at the same time, and the copy lasts only few seconds. In that case, it is easier to use that command to put all tablespaces in backup mode during the operation.

http://narashimreddy.wordpress.com/2009/09/11/oracle-backup-and-recovery-description-of-begin-backup-end-backup/


Oracle LOCAL INDEX를 drop하는 방법은 없습니다. ㅋ
아래 테스트를 보시면 local partition index로 만들어진 index는 drop이 되지 않는 군요.. 

LOCAL partition index는 partition table의 구조를 참조해서 만들어 지기 때문에 drop이 되지 않습니다. 
그러나 Global partition index는 자신만의 구조를 갖기 때문에 drop이 가능합니다.. 

+ LOCAL INDEX

SQL> create table p_emp (sal number(10))
 2  partition by range (sal)
 3   (partition emp_p1 values less than (2000),
 4    partition emp_p2 values less than (3000),
 5    partition emp_max values less than (maxvalue));

Table created.

SQL> create index p_emp_i on p_emp (sal) local;

Index created.

SQL> alter index p_emp_i drop partition emp_p1;
alter index p_emp_i drop partition emp_p1
           *
ERROR at line 1:
ORA-14076: submitted alter index partition/subpartition operation is not valid for local partitioned index

+ GLOBAL INDEX

 1  create table p_emp (empno number(4), sal number(10))
 2  partition by range (sal)
 3   (partition emp_p1 values less than (2000),
 4    partition emp_p2 values less than (3000),
 5*   partition emp_pmax values less than (maxvalue))
SQL> /

Table created.

 1  create index p_emp_i on p_emp (sal)
 2  global  partition by range (sal)
 3   (partition emp_p1 values less than (2000),
 4    partition emp_p2 values less than (3000),
 5*   partition emp_max values less than (maxvalue))
SQL> /

Index created.

SQL>
SQL> alter index p_emp_i drop partition emp_p2;

Index altered.

+ 참고

Truss 명령으로 system call 확인

% tusc -faepo /tmp/tusc.out -T %H:%M:%S -p <pid>

SQLNET tracing 

Client tracing
--------------
SQL*Net이 설치된 client 쪽 $ORACLE_HOME/network/admin/sqlnet.ora 파일에 다음을 추가해 주십시오.
TRACE_LEVEL_client=16
TRACE_FILE_client=client
TRACE_DIRECTORY_client=c:\temp /* trace 파일이 생성될 디렉토리 */
TRACE_UNIQUE_client=YES
TRACE_TIMESTAMP_client=ON

Listener tracing
-----------------
LISTENER.ORA 에 다음을 지정후 restart 합니다
TRACE_LEVEL_<listener_name>=16
TRACE_DIRECTORY_<listener_name>=/tmp
TRACE_FILE_<listener_name>=lsnr.trc
TRACE_TIMESTAMP_<listener name>=ON



UTL_FILE을 이용해 file을 loading 하는 아주 간단한 example. 

declare
   fp utl_file.file_type;
   str varchar2(48);
   VAL SCOTT.TEST%ROWTYPE;   
begin
   fp := utl_file.fopen('DATA_PUMP_DIR','sample_data.txt','r');
   loop
    utl_file.get_line(fp,str);
    VAL.CUST_ID := TRIM(SUBSTR(str,1,9));
    VAL.FC_ID := TRIM(SUBSTR(str,11,20));
    insert into SCOTT.TEST values(VAL.CUST_ID,VAL.FC_ID);
   end loop;
exception
when no_data_found then
   commit;
end;
/


네이버 지식인에 DBMS_JOB으로 만들어진 JOB의 interval을 1초로 지정해도 
5초 정도의 interval을 갖는다는 질문이 있어 간단히 테스트 해 봤습니다. 

DBMS_JOB package로 job을 생성합니다 
SQL> variable jobno number;
SQL> begin
SQL> dbms_job.submit(:jobno,'insert into test values (sysdate);',
SQL> sysdate,'sysdate+1/60/24/50',FALSE);
SQL> end;
SQL> /

PL/SQL procedure successfully completed.

SQL> print jobno
     JOBNO
----------
        21

SQL> exec dbms_job.run(21);
PL/SQL procedure successfully completed.

SQL> commit;
Commit complete.

SQL> select * from user_jobs;

       JOB LOG_USER                       PRIV_USER                      SCHEMA_USER                    LAST_DATE LAST_SEC         THIS_DATE THIS_SEC         NEXT_DATE NEXT_SEC         TOTAL_TIME B
---------- ------------------------------ ------------------------------ ------------------------------ --------- ---------------- --------- ---------------- --------- ---------------- ---------- -
INTERVAL
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  FAILURES
----------
WHAT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NLS_ENV
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MISC_ENV                                                           INSTANCE
---------------------------------------------------------------- ----------
        21 SYS                            SYS                            SYS                            12-OCT-10 16:50:28                                    12-OCT-10 16:50:29                  0 N
sysdate+1/60/24/50
         0
insert into test values (sysdate);
NLS_LANGUAGE='AMERICAN' NLS_TERRITORY='AMERICA' NLS_CURRENCY='$' NLS_ISO_CURRENCY='AMERICA' NLS_NUMERIC_CHARACTERS='.,' NLS_DATE_FORMAT='DD-MON-RR' NLS_DATE_LANGUAGE='AMERICAN' NLS_SORT='BINARY'
0102000202000000                                                          0

JOB 내역을 보면 정상적으로 NEXT_DATE는 LAST_DATE + 1초로 나옵니다 

SQL> alter session set nls_date_format = 'YYYY/MM/DD HH24:MI:SS';
Session altered.

SQL> select * from test;
COMMIT_DATE
-------------------
2010/10/12 16:50:04
2010/10/12 16:50:08
2010/10/12 16:50:13
2010/10/12 16:50:18
2010/10/12 16:50:23
2010/10/12 16:50:28
2010/10/12 16:50:33
2010/10/12 16:50:38
2010/10/12 16:50:43
2010/10/12 16:50:48
2010/10/12 16:50:53
2010/10/12 16:50:58
2010/10/12 16:51:03
2010/10/12 16:51:08

14 rows selected.

그러나 table에 들어간 시간을 보니 4초 차이가 발생하는 군요...

SQL> exec dbms_job.broken(21,TRUE);
PL/SQL procedure successfully completed.

SQL> exec dbms_job.remove(21);
PL/SQL procedure successfully completed.

SQL> delete from test;
25 rows deleted.

SQL> commit;
Commit complete.

이번엔 DBMS_SCHEDULER로 테스트 해봤습니다. 

SQL> begin
  2  dbms_scheduler.create_schedule(
schedule_name  => 'INTERVAL_EVERY_1_SECONDS',
  start_date    => trunc(sysdate),
  repeat_interval => 'freq=SECONDLY;interval=1',
  comments     => 'Runtime: Every day all 1 SECONDS');  3    4    5    6  
  7  end;
  8  /

PL/SQL procedure successfully completed.

1초에 한번씩 수행할 Schedule을 생성합니다 

SQL> begin
dbms_scheduler.create_program
(program_name=> 'TEST_PROC01',
 program_type=> 'STORED_PROCEDURE',
 program_action=> 'SYS.TEST_PROC',
 enabled=>true,
 comments=>'job interval test'
 );
end;
PL/SQL procedure successfully completed.

수행할 Program을 생성합니다. 
TEST_PROC는 test table에 sysdate를 입력하는 procedure 입니다.

SQL> begin
dbms_scheduler.create_job
 (job_name => 'JOB_TEST',
  program_name=> 'TEST_PROC01',
  schedule_name=>'INTERVAL_EVERY_1_SECONDS',
  enabled=>true,
  auto_drop=>false,
  comments=>'job test');
end;
/  
PL/SQL procedure successfully completed.

이제 먼저 생성한 schedule과 program을 이용해 JOB을 생성합니다 

SQL> begin
dbms_scheduler.run_job('JOB_TEST',TRUE);
end; 
/
PL/SQL procedure successfully completed.



SQL> select * from test;

COMMIT_DATE
-------------------
2010/10/12 17:12:38
2010/10/12 17:12:39
2010/10/12 17:12:40
2010/10/12 17:12:41
2010/10/12 17:12:42
2010/10/12 17:12:43
2010/10/12 17:12:44
2010/10/12 17:12:45
2010/10/12 17:12:46
2010/10/12 17:12:47
2010/10/12 17:12:48
2010/10/12 17:12:49
2010/10/12 17:12:50
2010/10/12 17:12:51
2010/10/12 17:12:52
2010/10/12 17:12:53
2010/10/12 17:12:54
2010/10/12 17:12:55
2010/10/12 17:12:55
2010/10/12 17:12:56
2010/10/12 17:12:57
2010/10/12 17:12:58
2010/10/12 17:12:59
2010/10/12 17:13:00
2010/10/12 17:13:01
...

table에 들어간 데이터를 보니 1초에 한번씩 수행하고 있군요.. 

DBMS_JOB을 이용한 job은 interval에 제한이 있는 걸까요? 그런 자료는 못 본것 같은데..

예전 oracle 8에서 job_queue_interval parameter가 있을때
수행 시간이 job_queue_interval 주기때문에 job interval이 정확히 계산되지 않았던 것 같은데... 
혹시 job_queue_process가 wake-up 하는 시간때문일까요?  






10. 10. 6 작성자: Laurent Schneider의 Laurent Schneider

Pretty straightforward, check if dbms_transaction.step_id is null!

SQL> select dbms_transaction.step_id from dual;
        STEP_ID
---------------

SQL> insert into t values (1);
1 row created.

SQL> select dbms_transaction.step_id from dual;
        STEP_ID
---------------
114352430549782

SQL> commit;
Commit complete.

SQL> select dbms_transaction.step_id from dual;
        STEP_ID
---------------


STEP_ID가 어떤의미일까요?
메뉴얼엔 step_id function에 대해 아래와 같이 정의도어 있는데, 무슨 말인지 잘 모르겠네요. 

"This function returns local (to local transaction) unique positive integer that orders the DML operations of a transaction."

테스트를 해보자면...

SQL> delete from yhcho_temp where col1 = 'TURNER';
1 row deleted.

SQL> select dbms_transaction.step_id from dual;
                   STEP_ID
--------------------------
         37783619732783637

SQL> savepoint A ;
Savepoint created.

SQL> delete from yhcho_temp where col1 = 'KING';
1 row deleted.

SQL> select dbms_transaction.step_id from dual;
                   STEP_ID
--------------------------
         37783619732783639

SQL> rollback to savepoint A;
Rollback complete.

SQL> select dbms_transaction.step_id from dual;
                   STEP_ID
--------------------------
         37783619732783639

savepoint A까지 rollback 해도 step_id는 바뀌지 않는 군요.. 
단순히 transaction step에 대한 sequence 일까요? 

SQL> delete from yhcho_temp where col1 = 'KING';
1 row deleted.

SQL> select dbms_transaction.step_id from dual;
                   STEP_ID
--------------------------
         37783619732783641

특정 transaction을 가리키는 것 같진 않고 
위의 post 처럼 step_id로는 단순히 transaction이 있는지 여부만 확인할 수 있을 것 같네요..

SQL> desc dbms_transaction        
PROCEDURE ADVISE_COMMIT
PROCEDURE ADVISE_NOTHING
PROCEDURE ADVISE_ROLLBACK
PROCEDURE BEGIN_DISCRETE_TRANSACTION
PROCEDURE COMMIT
PROCEDURE COMMIT_COMMENT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 CMNT                           VARCHAR2                IN
PROCEDURE COMMIT_FORCE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 XID                            VARCHAR2                IN
 SCN                            VARCHAR2                IN     DEFAULT
FUNCTION LOCAL_TRANSACTION_ID RETURNS VARCHAR2
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 CREATE_TRANSACTION             BOOLEAN                 IN     DEFAULT
PROCEDURE PURGE_LOST_DB_ENTRY
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 XID                            VARCHAR2                IN
PROCEDURE PURGE_MIXED
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 XID                            VARCHAR2                IN
PROCEDURE READ_ONLY
PROCEDURE READ_WRITE
PROCEDURE ROLLBACK
PROCEDURE ROLLBACK_FORCE
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 XID                            VARCHAR2                IN
PROCEDURE ROLLBACK_SAVEPOINT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SAVEPT                         VARCHAR2                IN
PROCEDURE SAVEPOINT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SAVEPT                         VARCHAR2                IN
FUNCTION STEP_ID RETURNS NUMBER
PROCEDURE USE_ROLLBACK_SEGMENT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 RB_NAME                        VARCHAR2                IN


library cache lock/pin은 library cache내의 object에 대한 매우 빠른 시간내에 처리되는 lock 메카니즘입니다.

따라서 일반적인 운영상황에서는 library cache lock/pin 등의 contention을 dump 등으로 정보를 수집하기는 엄청어렵죠.
뭐 운영중 DDL을 수행하면 library cache lock/pin을 유발할 순 있겠지만..

다음의 시나리오는 2006년 가을호 오라클 매거진에 있는 hang을 유발하는 시나리오 입니다.
(보고 싶은신 분들은 www.oracle.com에 가면 아마~ 있을 겁니다.)
오라클 매거진에서는 system state dump를 설명하고 있지만, 
요 시나리오를 이용해서 library cache dump를 떠보겠습니다. 

욱짜님의 오라클 블로그에 보면 "library cache pin self deadlock 만들기" 방법도 있습니다..

* 준비 과정

create table employee (empno number,ename varchar2(200), deptno number);
insert into employee values (1,'Alice',10);
commit;
create or replace procedure deleteEmployee(eno number)
is
begin
delete employee where empno = eno;
end;
/

* 시나리오
T1 (SID 110) : delete employee where empno = 1;
T2 (SID 92)  : exec deleteEmployee(1);
T3 (SID 67)  : alter procedure deleteEmployee compile;
T4 (SID 36)  : exec deleteEmployee(2);

alter session set events 'immediate trace name LIBRARY_CACHE level 11';


위와 같이 수행하게 되면 SID 92, 7, 36은 sql prompt가 떨어지지 않고 기다리게 됩니다.
각각 어떤 resource를 기다리고 있을까요?

* wait event
       SID EVENT                                  P1 P1RAW                    P2 P2RAW                    P3
---------- ------------------------------ ---------- ---------------- ---------- ---------------- ----------
        36 library cache lock             4.4044E+12 000004017D44D868 4.4040E+12 0000040163A70D88        201
        67 library cache pin              4.4044E+12 000004017D44D868 4.4040E+12 0000040163D23718        301
        92 enq: TX - row lock contention  1415053318 0000000054580006     131076 0000000000020004      31074
       110 SQL*Net message from client    1650815232 0000000062657100          1 0000000000000001          0

* lock info

ADDR             KADDR                   SID TY        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------
000004017E512348 000004017E512368         92 TX     131076      31074          0          6        144          0
000004017BBA0DC0 000004017BBA0DE8        110 TM     107693          0          3          0        150          0
000004017BBA0EC0 000004017BBA0EE8         92 TM     107693          0          3          0        144          0
000004017BC45998 000004017BC459D0        110 TX     131076      31074          6          0        150          1

wait event를 보면

SID 110이 "delete employee where empno = 1"을 수행해서 employee table에 대한 TM lock과 empno가 1인 row에 대한 TX lock을 획득하고 있습니다. 물론 commit을 하지 않아 그 상태가 계속 유지가 되죠.

SID 92는 "deleteEmployee(1)"을 수행해 empno가 1인 row를 지우려 하지만 이미 해당 row에 대한 lock을 SID 110이 갖고 있어 이를 기다리게 됩니다. 이 상태에서 해당 procedure는 현재 수행 중이기 때문에 library cache pin을 갖고 있게 됩니다.

SID 67은 deleteEmployee procedure를 수정하려 하기 때문에 관련 library cache lock과 pin이 필요하게 됩니다. 그러나 library cache pin은 현재 SID 92에서 갖고 있기 때문에 이를 기다려야 합니다.

SID 36은 "deleteEmployee(2)"를 수행하려 합니다. 그러나 deleteEmployee procedure를 수행하기 위해서는 library cache lock에 대한sahred lock을 할당 받아야 합니다.

우선 wait event에 있는 library cache handle 먼저 찾아 보겠습니다. (library cache lock/pin event는 p1 값이 library cache handle을, p2 값이 각각 library cache lock/pin address를 가리킵니다.)

아래 그림을 보시면 SCOTT.DELETEEMPLOYEE library cache object의 lock과 pin의 holder, waiter 정보를 확인할 수 있습니다. 그리고 DEPENDENCIES 항목을 보면 library cache object의 관련 object들도 list-up 된 것을 확인 할 수 있습니다.



library cache dump 등을 장애때 직접 수행해서 관련 정보를 분석할 일은 별로 없긴 하지만,
이를 통해 조금 더 오라클 내부 구조나 hang/lock 현상 등을 좀더 잘 이해 할 수 있는 과정이 될 수 있지 않을까 생각합니다.



+ Recent posts