Exadata의 cellserver는 기존의 disk server와 개념과 구조가 많이 달라

기본적으로 사용하고 있는 system 모니터링 툴의 기능 만으로 전반적인 내용을 판단하기 어렵습니다. 


Oracle Enterprise Manager를 사용해보신 분은 알겠지만..

오라클은 matric에 대한 임계치를 설정해 그에 따른 경고를 보내 주는 기능을 조아합니다. 

가장 많이 사용한 EM의 matric은 active session 등이 특정 개수 이상일 경우 경고해주는 등이죠..


Exadata의 cellserver도 그 와 비슷하게 여러 matric을 만들어 놓고 이에 따른 임계치를 설정할 수 있습니다. 

이 임계치 설정에 따라 미리 설정된 sms나 메일로 경고를 받아 볼 수 있습니다. 

아래 리스트는 Exadata cellserver에서 설정할 수 있는 전체 matric 입니다. 

대부분 성능에 대한 matric이나 file system 사용량이나 CPU 사용량, IO error 에 대한 임계치를 미리 설정할 만 하네요.


CellCLI> list METRICDEFINITION attributes name, description
         CD_IO_BY_R_LG                   "Number of megabytes read in large blocks from a cell disk"
         CD_IO_BY_R_LG_SEC               "Number of megabytes read in large blocks per second from a cell disk"
         CD_IO_BY_R_SM                   "Number of megabytes read in small blocks from a cell disk"
         CD_IO_BY_R_SM_SEC               "Number of megabytes read in small blocks per second from a cell disk"
         CD_IO_BY_W_LG                   "Number of megabytes written in large blocks to a cell disk"
         CD_IO_BY_W_LG_SEC               "Number of megabytes written in large blocks per second to a cell disk"
         CD_IO_BY_W_SM                   "Number of megabytes written in small blocks to a cell disk"
         CD_IO_BY_W_SM_SEC               "Number of megabytes written in small blocks per second to a cell disk"
         CD_IO_ERRS                      "Number of IO errors on a cell disk"
         CD_IO_ERRS_MIN                  "Number of IO errors on a cell disk per minute"
         CD_IO_RQ_R_LG                   "Number of requests to read large blocks from a cell disk"
         CD_IO_RQ_R_LG_SEC               "Number of requests to read large blocks per second from a cell disk"
         CD_IO_RQ_R_SM                   "Number of requests to read small blocks from a cell disk"
         CD_IO_RQ_R_SM_SEC               "Number of requests to read small blocks per second from a cell disk"
         CD_IO_RQ_W_LG                   "Number of requests to write large blocks to a cell disk"
         CD_IO_RQ_W_LG_SEC               "Number of requests to write large blocks per second to a cell disk"
         CD_IO_RQ_W_SM                   "Number of requests to write small blocks to a cell disk"
         CD_IO_RQ_W_SM_SEC               "Number of requests to write small blocks per second to a cell disk"
         CD_IO_ST_RQ                     "Average service time per request for small IO requests to a cell disk"
         CD_IO_TM_R_LG                   "Cumulative latency of reading large blocks from a cell disk"
         CD_IO_TM_R_LG_RQ                "Average latency of writing large blocks per request to a cell disk"
         CD_IO_TM_R_SM                   "Cumulative latency of reading small blocks from a cell disk"
         CD_IO_TM_R_SM_RQ                "Average latency of reading small blocks per request from a cell disk"
         CD_IO_TM_W_LG                   "Cumulative latency of writing large blocks to a cell disk"
         CD_IO_TM_W_LG_RQ                "Average latency of writing large blocks per request to a cell disk"
         CD_IO_TM_W_SM                   "Cumulative latency of writing small blocks to a cell disk"
         CD_IO_TM_W_SM_RQ                "Average latency of writing small blocks per request to a cell disk"
         CG_FC_IO_BY_SEC                 "Number of megabytes of I/O per second for this consumer group to flash cache"
         CG_FC_IO_RQ                     "Number of IO requests issued by a consumer group to flash cache"
         CG_FC_IO_RQ_SEC                 "Number of IO requests issued by a consumer group to flash cache per second"
         CG_FD_IO_BY_SEC                 "Number of megabytes of I/O per second for this consumer group to flash disks"
         CG_FD_IO_LOAD                   "Average I/O load from this consumer group for flash disks"
         CG_FD_IO_RQ_LG                  "Number of large IO requests issued by a consumer group to flash disks"
         CG_FD_IO_RQ_LG_SEC              "Number of large IO requests issued by a consumer group to flash disks per second"
         CG_FD_IO_RQ_SM                  "Number of small IO requests issued by a consumer group to flash disks"
         CG_FD_IO_RQ_SM_SEC              "Number of small IO requests issued by a consumer group to flash disks per second"
         CG_IO_BY_SEC                    "Number of megabytes of I/O per second for this consumer group to hard disks"
         CG_IO_LOAD                      "Average I/O load from this consumer group for hard disks"
         CG_IO_RQ_LG                     "Number of large IO requests issued by a consumer group to hard disks"
         CG_IO_RQ_LG_SEC                 "Number of large IO requests issued by a consumer group to hard disks per second"
         CG_IO_RQ_SM                     "Number of small IO requests issued by a consumer group to hard disks"
         CG_IO_RQ_SM_SEC                 "Number of small IO requests issued by a consumer group to hard disks per second"
         CG_IO_UTIL_LG                   "Percentage of disk resources utilized by large requests from this consumer group"
         CG_IO_UTIL_SM                   "Percentage of disk resources utilized by small requests from this consumer group"
         CG_IO_WT_LG                     "IORM wait time for large IO requests issued by a consumer group"
         CG_IO_WT_LG_RQ                  "Average IORM wait time per request for large IO requests issued by a consumer group"
         CG_IO_WT_SM                     "IORM wait time for small IO requests issued by a consumer group"
         CG_IO_WT_SM_RQ                  "Average IORM wait time per request for small IO requests issued by a consumer group"
         CL_CPUT                         "Cell CPU Utilization is the percentage of time over the previous minute that the system CPUs were not idle (from /proc/stat)."
         CL_FANS                         "Number of working fans on the cell"
         CL_FSUT                         "Percentage of total space on this file system that is currently used"
         CL_MEMUT                        "Percentage of total physical memory on the cell that is currently used"
         CL_RUNQ                         "Average number (over the preceding minute) of processes in the Linux run queue marked running or uninterruptible (from /proc/loadavg)."
         CL_TEMP                         "Temperature (Celsius) of the server, provided by the BMC"
         CT_FC_IO_BY_SEC                 "Number of megabytes of I/O per second for this category to flash cache"
         CT_FC_IO_RQ                     "Number of IO requests issued by an IORM category to flash cache"
         CT_FC_IO_RQ_SEC                 "Number of IO requests issued by an IORM category to flash cache per second"
         CT_FD_IO_BY_SEC                 "Number of megabytes of I/O per second for this category to flash disks"
         CT_FD_IO_LOAD                   "Average I/O load from this category for flash disks"
         CT_FD_IO_RQ_LG                  "Number of large IO requests issued by an IORM category to flash disks"
         CT_FD_IO_RQ_LG_SEC              "Number of large IO requests issued by an IORM category to flash disks per second"
         CT_FD_IO_RQ_SM                  "Number of small IO requests issued by an IORM category to flash disks"
         CT_FD_IO_RQ_SM_SEC              "Number of small IO requests issued by an IORM category to flash disks per second"
         CT_IO_BY_SEC                    "Number of megabytes of I/O per second for this category to hard disks"
         CT_IO_LOAD                      "Average I/O load from this category for hard disks"
         CT_IO_RQ_LG                     "Number of large IO requests issued by an IORM category to hard disks"
         CT_IO_RQ_LG_SEC                 "Number of large IO requests issued by an IORM category to hard disks per second"
         CT_IO_RQ_SM                     "Number of small IO requests issued by an IORM category to hard disks"
         CT_IO_RQ_SM_SEC                 "Number of small IO requests issued by an IORM category to hard disks per second"
         CT_IO_UTIL_LG                   "Percentage of disk resources utilized by large requests from this category"
         CT_IO_UTIL_SM                   "Percentage of disk resources utilized by small requests from this category"
         CT_IO_WT_LG                     "IORM wait time for large IO requests issued by an IORM category"
         CT_IO_WT_LG_RQ                  "Average IORM wait time per request for large IO requests issued by an IORM category"
         CT_IO_WT_SM                     "IORM wait time for small IO requests issued by an IORM category"
         CT_IO_WT_SM_RQ                  "Average IORM wait time per request for small IO requests issued by an IORM category"
         DB_FC_IO_BY_SEC                 "Number of megabytes of I/O per second for this database to flash cache"
         DB_FC_IO_RQ                     "Number of IO requests issued by a database to flash cache"
         DB_FC_IO_RQ_SEC                 "Number of IO requests issued by a database to flash cache per second"
         DB_FD_IO_BY_SEC                 "Number of megabytes of I/O per second for this database to flash disks"
         DB_FD_IO_LOAD                   "Average I/O load from this database for flash disks"
         DB_FD_IO_RQ_LG                  "Number of large IO requests issued by a database to flash disks"
         DB_FD_IO_RQ_LG_SEC              "Number of large IO requests issued by a database to flash disks per second"
         DB_FD_IO_RQ_SM                  "Number of small IO requests issued by a database to flash disks"
         DB_FD_IO_RQ_SM_SEC              "Number of small IO requests issued by a database to flash disks per second"
         DB_IO_BY_SEC                    "Number of megabytes of I/O per second for this database to hard disks"
         DB_IO_LOAD                      "Average I/O load from this database for hard disks"
         DB_IO_RQ_LG                     "Number of large IO requests issued by a database to hard disks"
         DB_IO_RQ_LG_SEC                 "Number of large IO requests issued by a database to hard disks per second"
         DB_IO_RQ_SM                     "Number of small IO requests issued by a database to hard disks"
         DB_IO_RQ_SM_SEC                 "Number of small IO requests issued by a database to hard disks per second"
         DB_IO_UTIL_LG                   "Percentage of disk resources utilized by large requests from this database"
         DB_IO_UTIL_SM                   "Percentage of disk resources utilized by small requests from this database"
         DB_IO_WT_LG                     "IORM wait time for large IO requests issued by a database"
         DB_IO_WT_LG_RQ                  "Average IORM wait time per request for large IO requests issued by a database"
         DB_IO_WT_SM                     "IORM wait time for small IO requests issued by a database"
         DB_IO_WT_SM_RQ                  "Average IORM wait time per request for small IO requests issued by a database"
         FC_BYKEEP_OVERWR                "Number of megabytes pushed out of the FlashCache because of space limit for 'keep' objects"
         FC_BYKEEP_OVERWR_SEC            "Number of megabytes per second pushed out of the FlashCache because of space limit for 'keep' objects"
         FC_BYKEEP_USED                  "Number of megabytes used for 'keep' objects on FlashCache"
         FC_BY_USED                      "Number of megabytes used on FlashCache"
         FC_IO_BYKEEP_R                  "Number of megabytes read from FlashCache for 'keep' objects"
         FC_IO_BYKEEP_R_SEC              "Number of megabytes read per second from FlashCache for 'keep' objects"
         FC_IO_BYKEEP_W                  "Number of megabytes written to FlashCache for 'keep' objects"
         FC_IO_BYKEEP_W_SEC              "Number of megabytes per second written to FlashCache for 'keep' objects"
         FC_IO_BY_R                      "Number of megabytes read from FlashCache"
         FC_IO_BY_R_MISS                 "Number of megabytes read from disks because not all requested data was in FlashCache"
         FC_IO_BY_R_MISS_SEC             "Number of megabytes read from disks per second because not all requested data was in FlashCache"
         FC_IO_BY_R_SEC                  "Number of megabytes read per second from FlashCache"
         FC_IO_BY_R_SKIP                 "Number of megabytes read from disks for IO requests with a hint to bypass FlashCache"
         FC_IO_BY_R_SKIP_SEC             "Number of megabytes read from disks per second for IO requests with a hint to bypass FlashCache"
         FC_IO_BY_W                      "Number of megabytes written to FlashCache"
         FC_IO_BY_W_SEC                  "Number of megabytes per second written to FlashCache"
         FC_IO_ERRS                      "Number of IO errors on FlashCache"
         FC_IO_RQKEEP_R                  "Number of read IO requests for 'keep' objects satisfied from FlashCache"
         FC_IO_RQKEEP_R_MISS             "Number of read IO requests for 'keep' objects which did not find all data in FlashCache"
         FC_IO_RQKEEP_R_MISS_SEC         "Number of read IO requests per second for 'keep' objects which did not find all data in FlashCache"
         FC_IO_RQKEEP_R_SEC              "Number of read IO requests for 'keep' objects per second satisfied from FlashCache"
         FC_IO_RQKEEP_R_SKIP             "Number of read IO requests for 'keep' objects with a hint to bypass FlashCache"
         FC_IO_RQKEEP_R_SKIP_SEC         "Number of read IO requests per second for 'keep' objects with a hint to bypass FlashCache"
         FC_IO_RQKEEP_W                  "Number of IO requests for 'keep' objects which resulted in FlashCache being populated with data"
         FC_IO_RQKEEP_W_SEC              "Number of IO requests per second for 'keep' objects which resulted in FlashCache being populated with data"
         FC_IO_RQ_R                      "Number of read IO requests satisfied from FlashCache"
         FC_IO_RQ_R_MISS                 "Number of read IO requests which did not find all data in FlashCache"
         FC_IO_RQ_R_MISS_SEC             "Number of read IO requests per second which did not find all data in FlashCache"
         FC_IO_RQ_R_SEC                  "Number of read IO requests satisfied per second from FlashCache"
         FC_IO_RQ_R_SKIP                 "Number of read IO requests with a hint to bypass FlashCache"
         FC_IO_RQ_R_SKIP_SEC             "Number of read IO requests per second with a hint to bypass FlashCache"
         FC_IO_RQ_W                      "Number of IO requests which resulted in FlashCache being populated with data"
         FC_IO_RQ_W_SEC                  "Number of IO requests per second which resulted in FlashCache being populated with data"
         FD_IO_LOAD                      "Average I/O load for flash disks"
         GD_IO_BY_R_LG                   "Number of megabytes read in large blocks from a grid disk"
         GD_IO_BY_R_LG_SEC               "Number of megabytes read in large blocks per second from a grid disk"
         GD_IO_BY_R_SM                   "Number of megabytes read in small blocks from a grid disk"
         GD_IO_BY_R_SM_SEC               "Number of megabytes read in small blocks per second from a grid disk"
         GD_IO_BY_W_LG                   "Number of megabytes written in large blocks to a grid disk"
         GD_IO_BY_W_LG_SEC               "Number of megabytes written in large blocks per second to a grid disk"
         GD_IO_BY_W_SM                   "Number of megabytes written in small blocks to a grid disk"
         GD_IO_BY_W_SM_SEC               "Number of megabytes written in small blocks per second to a grid disk"
         GD_IO_ERRS                      "Number of IO errors on a grid disk"
         GD_IO_ERRS_MIN                  "Number of IO errors on a grid disk per minute"
         GD_IO_RQ_R_LG                   "Number of requests to read large blocks from a grid disk"
         GD_IO_RQ_R_LG_SEC               "Number of requests to read large blocks per second from a grid disk"
         GD_IO_RQ_R_SM                   "Number of requests to read small blocks from a grid disk"
         GD_IO_RQ_R_SM_SEC               "Number of requests to read small blocks per second from a grid disk"
         GD_IO_RQ_W_LG                   "Number of requests to write large blocks to a grid disk"
         GD_IO_RQ_W_LG_SEC               "Number of requests to write large blocks per second to a grid disk"
         GD_IO_RQ_W_SM                   "Number of requests to write small blocks to a grid disk"
         GD_IO_RQ_W_SM_SEC               "Number of requests to write small blocks per second to a grid disk"
         IORM_MODE                       "I/O Resource Manager objective for the cell"
         IO_LOAD                         "Average I/O load for hard disks"
         N_MB_DROP                       "Number of megabytes droped during  transmission  to  a particular host"
         N_MB_DROP_SEC                   "Number of megabytes droped during transmission  per second  to  a particular host"
         N_MB_RDMA_DROP                  "Number of megabytes dropped during RDMA transmission to  a particular host"
         N_MB_RDMA_DROP_SEC              "Number of megabytes dropped during RDMA transmission per second  to  a particular host"
         N_MB_RECEIVED                   "Number of megabytes received from a particular host"
         N_MB_RECEIVED_SEC               "Number of megabytes per second received from a particular host"
         N_MB_RESENT                     "Number of megabytes resent  to  a particular host"
         N_MB_RESENT_SEC                 "Number of megabytes resent per second to  a particular host"
         N_MB_SENT                       "Number of megabytes transmitted to  a particular host"
         N_MB_SENT_SEC                   "Number of megabytes transmitted per second to  a particular host"
         N_NIC_NW                        "Number of non-working interconnects"
         N_NIC_RCV_SEC                   "Total number of IO packets received by interconnects per second"
         N_NIC_TRANS_SEC                 "Total number of IO packets transmitted by interconnects per second"
         N_RDMA_RETRY_TM                 "Latency of the retry actions during RDMA transmission to a particular host"


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




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을 같이 넘겨여 한다.
안그러면 순서가 뒤죽박죽~ 될 수 있음.  

오라클 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


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 등에서 어떤 상태로 보여질까요? 



> 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
네이버 지식인에 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



사용자 table 데이터 중에서 꼭 변경되면 안되는 데이터는 반드시 있기마련입니다. 
예를 들자면, 이름과 주민등록 번호, 학생과 학번, 등등..

위의 데이터 처럼 입력은 가능해야 하나 한번 입력된 특정 column을 변경되지 않게 하기 위해서는 어떤 방법이 있을까요? 
가장 쉽게 생각할 수 있는게 trigger 입니다. 
다음은 trigger를 이용해 특정 column을 변경하지 못하게 설정하는 trigger sample 입니다. 

(사실 trigger 이외에 딱히 생각나는 방법이 없네요 --;)

1. SCOTT user의 EMP table에 trigger를 설정합니다. 

CREATE TRIGGER emp_upd_trigger
BEFORE UPDATE on emp
declare
    v_error VARCHAR2(256);
begin
    if (updating('EMPNO') or updating('ENAME'))
     then
         v_error:='You cannot update the empno';
         raise_application_error (-20999,v_error);
     end if;
end;
/

2. trigger가 만들어 졌으면 간단히 테스트를 해볼까요? 

SQL> select * from emp;

     EMPNO ENAME                          JOB                                MGR HIREDATE          SAL       COMM     DEPTNO
---------- ------------------------------ --------------------------- ---------- ---------- ---------- ---------- ----------
      7900 JAMES                          CLERK                             7698 1981-12-03        950                    30
      7902 FORD                           ANALYST                           7566 1981-12-03       3000                    20
      7934 MILLER                         CLERK                             7782 1982-01-23       1300                    10

SQL> update emp set empno = 9999 where ename = 'MILLER';
update emp set empno = 9999 where ename = 'MILLER'
       *
ERROR at line 1:
ORA-20999: You cannot update the empno or ename
ORA-06512: at "SCOTT.EMP_UPD_TRIGGER", line 7
ORA-04088: error during execution of trigger 'SCOTT.EMP_UPD_TRIGGER'

SQL> update emp set ename = 'ORACLE' where empno = 7934;
update emp set ename = 'ORACLE' where empno = 7934
       *
ERROR at line 1:
ORA-20999: You cannot update the empno or ename
ORA-06512: at "SCOTT.EMP_UPD_TRIGGER", line 7
ORA-04088: error during execution of trigger 'SCOTT.EMP_UPD_TRIGGER'

이 방법 이외에 다른 방법 아시는 분.. 
좀 알려주세요.. ^^


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




We promised in an earlier post to cover some of the questions from the Optimizer round table discussion at Oracle Open World. Here's our first in a series of posts that will address these questions. 

Q: When moving from 10g to 11g, should hints in existing SQL be removed? 

A: I was glad to see this question at the round table, since I think this is something people often overlook when adding hints to an application. Over time, hints can become stale. You may have added a hint to a query because of a weakness in an old version of the optimizer, but the hint might no longer be necessary to get the best plan. Even worse, the hint may force a plan which is suboptimal, for a couple of reasons:

이 질문은 오라클 데이터베이스 관계자라면 매우 자주 듣는 질문이죠. 
이전 버전의 SQL에 적용된 hint를 제거하는게 맞을까요? 아님 계속 사용하는게 맞을까요? 
물론 답은 당연히 제거하라 겠죠? 

새로운 버전에서, 그리고 변경되는 데이터 상에서 해당 hint가 적정할지,
또 hint를 사용한 사람이 선택한 plan이 과연 적정할지.. 
그 hint는 새로운 버전에서 계속 존재하는지..
이러한 판단이 가능한 사람이 있을까 모르겠네요.. 

위의 포스트는 오라클 optimizer 팀 blog의 post 입니다. open world에서 질문 나온걸 정리한다네요. 
한번 읽어 보세요 ~
baseline을 이용한 plan 고정하는 방법도 나오네요..

그나저나 _optimizer_ignore_hints parameter는 언제 생긴걸까? 
이거 쓸만할 거 같은데, 확인 좀 해 봐야겠네요~


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



CROSS JOIN/ Cartesian Products

 - Cartesian product 값을 얻을때 사용 합니다. 
 - 즉 join을 통해 생성가능한 모든 row를 return 합니다. 

SQL>SELECT ename FROM emp CROSS JOIN dept;
SQL>SELECT ename FROM emp, dept;

참고: CROSS가 생략되어 INNER join으로 수행되는 경우(join condition이 없는 경우) 나 CROSS join에서 join condition이 기술된 경우 에러발생합니다. 

SQL>SELECT e.lname, d.name FROM employee e JOIN department d;
ORA-00905: missing keyword

SQL>SELECT e.lname, d.name FROM employee e CROSS JOIN department d ON e.dept_id = d.dept_id;
ORA-00933: SQL command not properly ended


INNER JOIN 

 - 일반 조인시 Table간의 ','를 생략하고 'INNER JOIN'을 추가하고 WHERE절대신 ON절을 사용해야 합니다.
 - INNER는 생략 가능합니다.

SQL>SELECT e.empno, e.ename FROM dept d INNER JOIN emp e ON d.deptno=e.deptno;
SQL>SELECT e.empno, e.ename FROM dept d , emp e WHERE d.deptno=e.deptno;

EQUI-JOIN/ NON-EQUI-JOIN 
 - Join condition에 equal operation(=)을 사용하는 JOIN 
 - Join condition에 equal operation 외의 다른 operation을 사용하는 JOIN

SQL> SELECT s.name supplier_name, p.name part_name FROM supplier s JOIN part p ON s.supplier_id = p.supplier_id;
SQL> SELECT p.name part_name, c.inv_class inv_class FROM part p JOIN inventory_class c ON p.unit_cost BETWEEN c.low_cost AND c.high_cost;

SELF JOIN
 - 동일 TABLE에 대한 JOIN

SQL> SELECT e.lname employee, m.lname manager FROM employee e JOIN employee m ON e.manager_emp_id = m.emp_id;

OUTER JOIN 

 - Join시 특정 table의 join 조건에 일치하지 않은 row를 추가할때 사용해야 합니다.
 - { LEFT | RIGHT | FULL } [OUTER]

SQL>SELECT e.empno, e.ename FROM dept d LEFT OUTER JOIN emp e ON d.deptno=e.deptno;
SQL>SELECT e.empno, e.ename FROM dept d , emp e WHERE d.deptno=e.deptno(+);

SQL>SELECT e.empno, e.ename FROM dept d RIGHT OUTER JOIN emp e ON d.deptno=e.deptno;
SQL>SELECT e.empno, e.ename FROM dept d , emp e WHERE d.deptno(+)=e.deptno;

SQL>SELECT e.empno, e.ename FROM dept d FULL OUTER JOIN emp e ON d.deptno=e.deptno;

참고: full outer join의 비밀 [Science of DataBase]


PARTITION OUTER JOIN 

 - PARTITION OUTER JOIN을 사용하여 분석 대상이 되는 디멘션의 densification을 수행할 수 있으며, 
 - 파티션이나 테이블 내부에서 OUTER JOIN을 적용할 수 있습니다.

select hiredate,d.dname,  nvl(sum_sal,0) sum_sal
from dept d
left outer join (select deptno,to_char(hiredate,'YYYY') hiredate, sum(sal) sum_sal from emp group by deptno,to_char(hiredate,'YYYY')) e
partition by (e.hiredate)
on d.deptno = e.deptno
order by 1,2
/

HIREDATE     DNAME                                         SUM_SAL
------------ ------------------------------------------ ----------
1980         ACCOUNTING                                          0
1980         OPERATIONS                                          0
1980         RESEARCH                                          800
1980         SALES                                               0
1981         ACCOUNTING                                       7450
1981         OPERATIONS                                          0
1981         RESEARCH                                         5975
1981         SALES                                            9400
1982         ACCOUNTING                                       1300
1982         OPERATIONS                                          0
1982         RESEARCH                                         3000
1982         SALES                                               0
1983         ACCOUNTING                                          0
1983         OPERATIONS                                          0
1983         RESEARCH                                         1100
1983         SALES                                               0



NATURAL JOIN 

 - Equijoin과 동일하다고 보시면 됩니다.
 - 두 테이블의 동일한 이름을 가지는 칼럼은 모두 조인이 됩니다. (oracle forum : HR유저에서 NATURAL JOIN 결과가 다릅니다 )
 - 동일한 컬럼을 내부적으로 찾게 되므로 테이블 Alias를 주면 오류가 발생 합니다. 
    (ORA-25155: column used in NATURAL join cannot have qualifier)
 - 동일한 컬럼이 두개 이상일 경우 JOIN~USING문장으로 조인되는 컬럼을 제어 할 수 있습니다.
 
SQL>SELECT empno, ename, deptno FROM emp NATURAL JOIN dept 
SQL>SELECT e.empno, e.ename, d.deptno FROM emp e, dept d WHERE e.deptno=d.deptno


JOIN ~ USING 

 - NATURAL JOIN의 단점은 동일한 이름을 가지는 칼럼은 모두 조인이 되었는데 USING 문을 사용하면 컬럼을 선택해서 조인을 할 수가 있습니다.
 - USING절 안에 포함되는 컬럼에 Alias를 지정하면 오류가 발생 합니다.
  
SQL>SELECT e.empno, e.ename, deptno FROM emp e JOIN dept d USING(deptno)


ON 구문

 - 조인 조건을 지정 할 수 있습니다. 
 - 모든 논리 연산 및 서브쿼리를 지정할 수 있습니다.

SQL>SELECT e.empno, e.ename, e.sal
       FROM emp e JOIN dept    d  ON (e.deptno=d.deptno)
                           JOIN bonus  b ON (b.ename = e.ename)
       WHERE e.sal IS NOT NULL




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



가끔 문제가 있어 alert log file이나 event 설정해 놓은 걸 보면 trace file이 있을거로 예상 되어지는데, 실제 trace 파일 등이 없는 경우가 있습니다. 대부분 부족한 filesystem 때문에 oracle home 내의 trace file을 주기적으로 정리하느라 없어지는 경우가 대부분이죠. 
 
이럴 경우, unix 상에서 trace 파일을 지우면 그 trace 파일을 오픈하고 있는 process는 계속해서 write를 할 수 있기때문에, 결국은 trace file에 열심히 기록을 해 놓아도 볼 수 없게 됩니다.  결국은 내렸다 올리면 process들이 trace file을 새로 생성하게되니 문제가 해결되지만, oradebug를 사용하면 process를 내리지 않고 trace file을 다시 생성하게 할 수 있습니다. 
 
oradebug setospid <ospid>
oradebug close_trace

위의 명령을 수행하면 현재까지 process가 잡고 있던 trace file을 close 하게 되고 이 후 process가 trace file에 기록할 내용이 발생하면 trace file을 새로 생성하고 기록하게 됩니다. 물론 이미 존재하는 trace file이 있다면 마지막 부분에 file의 header를 모두 기록하고 시작하게 됩니다.



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



10g 부터는 Oracle에서 자동으로 optimizer statistic 통계정보를 수집하게 됩니다.
11g에는 scheduler job에서 automated task로 변경된 거 같은데,
모두 마찬가지로 10% 이상의 변경을 대상으로 수집합니다. (11g 두? .. 음)

다음의 SQL은 dba_tab_modifications table에서 DML에 의해 변경된 건수와 dba_tables의 num_rows를 비교해
10% 이상 변경된 table을 조회하는 SQL 문입니다.

select TABLE_OWNER,m.TABLE_NAME,num_rows,round(num_rows/10,0) "NUM_ROWS/10",inserts+updates+deletes "tot_changed",
INSERTS,UPDATES,DELETES,TIMESTAMP,LAST_ANALYZED,round(LAST_ANALYZED-TIMESTAMP,0) GAP
from dba_tab_modifications  m, dba_tables t
where table_owner not in ('SYS')
and t.table_name = m.table_name
and t.owner = m.table_owner
and round(num_rows/10,0) - (inserts+updates+deletes) < 0
order by LAST_ANALYZED-TIMESTAMP
/

UPDATE (2010/07/05)

아래 블로그는 제가 구독하는 Oracle 관련 blog 입니다.
dba_tab_modifications에 대해 자세한 설명과 test 결과를 post 해 놓았네요. dba_tab_modifications의 데이터가 즉각적으로 보이지 않던데, 
flush를 해줘야 하는 군요.. 움~

exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO








Database system 운영 시 listener 관련 장애들은 크게 두가지입니다.
listener가 죽던지, 멍청하게 멈춰서 아무일도 못하든지.. 
다음은 listener가 멍청하게 멈춰서 아무일도 못하는 경우에 문제 해결을 위해 정보를 수집하는 방법입니다.


hang 문제가 발생하면 가장 손쉽게 접근할 수 있는 방법이 listener에 log를 설정해서 문제가 발생할 때 어떤 일이 있었는지를 확인하는 방법입니다.
하지만 문제가 언제쯤 발생할지 모르는 상태라면 log의 설정은 문제 발생 전까지 끊임 없는 관리가 필요합니다. 
클라이언트에서 접속하는 모든 정보까지 log에 저장하게 되므로 관리해 놓지 않으면 나중에 log file을 vi로 열기도 힘들어 집니다. 
따라서 매일 (혹은 몇일마다) listener log를 flush 하기 위해 listener restart(reload) 작업을 해주면서 log file을 관리해야 합니다. 

다음의 방법은 log 설정하지 않고 문제가 발생하는 시점에 인지를 할 수 있다면 다소 유용할 수 있는 방법입니다. 
즉, hang 상태가 발생했을때 어떤 O/S system call에서 멈춰있는지를 확인할 수 있는 두가지 방법입니다. 

process의 stack 정보를 확인하는, PSTACK 명령과 GDB 명령입니다. 

1. pstack <listener_pid> 
2. gdb $ORACLE_HOME/bin/tnslsnr <listener_pid>
   (gdb) info thread
   (gdb) thread 1
   (gdb) where
   (gdb) 반복 (thread 숫자만큼)
   (gdb) quit


위와 같이 수행하는 경우 listener가 어떤 call stack에서 멈춰있는지를 확인할 수 있습니다. 
이렇게 call stack을 수집하는 이뉴는 발생한 문제가 이미 보고된 bug과 동일한 문제가 있는지의 확인이 쉽기 때문입니다. 

만약 call stack으로 bug을 확인했을때 비슷한 문제가 없다면, 새로 분석을 진행해야 하니 
listener log의 설정을 다시 요구할 수도 있습니다..만 



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





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 기능을 사용하고 있지 않아 더이상 깊이는 무리.. 


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


 
오라클은 사용자 작업을 위해 많은 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
 

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')
/
(왠지 좀 무지해 보이는데.. 더 좋은 방법이 있으면 알려주세요 *^^*)


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



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 등의 값의 영향으로 약간의 가감은 필요할 것 같습니다만.
대충 얼마정도의 공간이 필요할 것이다라는 것에 대한 힌트는 될 것 같습니다.



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





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;


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



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

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




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





오라클의 전체적인 사용현황과 그에 따른 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)








+ Recent posts