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




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) 

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


블로그 구경다니다가 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)에는 그런 내용은 없는 것 같습니다. 
요 방법 써도 괜찮을라나? 

네이버 지식인에 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. 8. 16 작성자: April C Sims의 Oracle High Availability

New error logging facility in 11g…spool errors from a table that traps them. Table is automatically created after using the SET command in SQLPLUS.

Data stored in the sperrorlog persists between sessions and whether it is interactive or non-interactive such as a script.

Should you turn on errorlogging for SYS?  Sort of a catchall auditing for errors not ordinarily trapped? I am turning on sperrorlog for SYS in a non-production 11gR2 database to see what happens.

New 11g SQLPLUS Parameter ERRORLOGGING [ID 471066.1]


11g에서는 sqlplus에서 발생하는 에러를 logging 할 수 있다는 군요. 
(이 사람들은 새로운 버전 나올때 마다 모든 메뉴얼을 다 보는 것일까요? 존경스럽습니다.. )

위의 내용보고 따라해 봤습니다..

$ sqlplus system
SQL> set errorlogging on
SQL> select * from sperrorlog;

no rows selected

SQL> select * from scott.emp;
select * from scott.emp
                    *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> set pagesize 200
SQL> select * from sperrorlog;

USERNAME
--------------------------------------------------------------------------------
TIMESTAMP
---------------------------------------------------------------------------
SCRIPT
--------------------------------------------------------------------------------
IDENTIFIER
--------------------------------------------------------------------------------
MESSAGE
--------------------------------------------------------------------------------
STATEMENT
--------------------------------------------------------------------------------
SYSTEM
2010-09-17-13.53.55.000000


ORA-00942: table or view does not exist
select * from scott.emp

잘 되는 군요..
sqlplus를 재 접속해도 위의 에러정보는 계속 남습니다. 

그러면 purge는 어떻게 할까요? 
따로 나와있는 내용이 없는 거 같으니, 아마 delete나 truncate로 해야하는 거 같긴한데..
요건 좀 나중에 확인해 보고..

user가 table을 만들고 이걸 지정할 수 도 있답니다. 

SQL>  SET ERRORLOGGING ON TABLE enduser_sperrorlog;

위의 블로그 한번 들러 보시지요~ ^^


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는 언제 생긴걸까? 
이거 쓸만할 거 같은데, 확인 좀 해 봐야겠네요~


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



+ INVISIBLE index 생성 
SQL> create index emp_idx01 on emp(empno) invisible;

Index created.

+ 일반 세션에서 SQL 수행 
SQL> set autot on exp
SQL> 
SQL> select empno from emp where empno = 7839;

     EMPNO
----------
      7839

Execution Plan
----------------------------------------------------------
Plan hash value: 2872589290

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     4 |    12   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     4 |    12   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7839)

+ INVISIBLE INDEX 사용 정의
SQL> alter session set optimizer_use_invisible_indexes=true;

Session altered.

SQL> select empno from emp where empno = 7839;

     EMPNO
----------
      7839


Execution Plan
----------------------------------------------------------
Plan hash value: 3956893595

------------------------------------------------------------------------------
| Id  | Operation        | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |           |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| EMP_IDX01 |     1 |     4 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("EMPNO"=7839)

+ INVISIBLE INDEX 사용 해제
SQL> alter session set optimizer_use_invisible_indexes=false;

Session altered.

SQL> select empno from emp where empno = 7839;

     EMPNO
----------
      7839


Execution Plan
----------------------------------------------------------
Plan hash value: 2872589290

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     4 |    12   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     4 |    12   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7839)

+ OPT_PARAM hint를 통한 INVISIBLE index 사용 권한 부여 -> 실패 ?
SQL> select /*+ opt_param('optimizer_use_invisible_indexes','true') */ empno from emp where empno = 7839;

     EMPNO
----------
      7839


Execution Plan
----------------------------------------------------------
Plan hash value: 2872589290

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     4 |    12   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     4 |    12   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7839)

데이터 파일의 저장공간을 넉넉히 갖고 운영할 수 있으면 좋겠지만, 대부분의 사이트 들은 한정된 disk 공간으로 운영을 합니다.  Disk의 가격도 만만치 않거니와 향후 발생할 데이터 양을 너무 빡빡하게 계산해 놓으면 이 한정된 disk를 알뜰하게 DBA들이 사용해야 하죠. 

Disk의 공간을 줄이기 위해 compress table이나 table re-org 작업, tablespace shrink 작업들을 하게되는데 오늘은 Bulletin 10165의 내용을 정리합니다. 

tablespace shrink 작업은 extent가 할당되지 않은 공간 중 마지막 extent 부분 부터 줄일 수 있습니다. 즉, tablespace가 처음 할당 되고 얼마 되지 않은 table 들이 생성됬을 경우 꽤 짭짭할 공간을 줄일 수 있겠지만, 이미 사용한지 좀 된 tablespace의 경우에는 중간중간 extent가 할당되어 얼마 못 줄이게 됩니다. 이런 경우에는 table을 drop하고 재 생성하는 등의 re-org 작업이 선행 되거나 tablespace를 이리저리 건너 뛰면서 줄여야 됩니다. 

그럼 tablespace를 resize 할 수 있는 max size를 어떻게 구할 수 있을까요? 

dba_extents라는 view를 보면 datafile 별로 extent가 할당된 정보가 나옵니다. 이 할당된 extent의 마지막 위치를 파악해서 바로 그 이후로 size를 지정하면 됩니다.  다음의 공식은 bulletin 10165에 나와 있는 공식입니다. 

1) 줄이고자하는 file id를 확인합니다.
SQLPLUS> select file_id, file_name from dba_data_files;

2) 얼마를 사용했는지 확인합니다.
SQLPLUS> select block_id, blocks from dba_extents where file_id='FILE_ID' order by block_id;

FILE_ID 대신에 줄이려는 file id를 기술합니다.

3)현재 사용중이 db block size를 확인합니다.
SQLPLUS> show parameter db_block_size

2)에서 조회된 마지막의 block_id, blocks 값을 가지고 계산합니다. 
block_id * db_block_size + blocks * db_block_size 의 결과에 한 block더한 값만큼만 줄이는 것이 가능합니다. 

만일 마지막으로 조회된 값이 block_id가 578261, blocks가 515, db_block_size가 2048 일 경우  
578261*2048 + 515*2048 =1185333248로 최소한 1.2GB이상은 써야 합니다. 

4) 실제 datafile을 줄입니다.
SQLPLUS>alter database datafile '/oracle/dbs/toolsORA.dbf' resize 1200M;



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



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 - 유사한 페이지






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


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

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

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

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

adrci> help purge

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

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

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

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

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

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

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


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



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

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

1. table 생성 및 데이터 입력

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

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

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

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

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

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

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

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

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

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

SQL> select * from scott.emp_REDEF;

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

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

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

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

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




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



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

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

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

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

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

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

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


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



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






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






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

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

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

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

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

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

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

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

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

$ adrci

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

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

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

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

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

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

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





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

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

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

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






Oracle INVISIBLE index는 Oracle 11g new feature 입니다.

말 그대로 보이지 않는 index 입니다. 여기서 보는 주체는 oracle optimizer가 됩니다.
즉 index는 존재하지만 optimizer는 이를 기준으로 plan을 생성하지 않습니다.
그러나 해당 index의 table에 대한 DML 변경 내역은 모두 index에 적용되게 됩니다.

이는 index 생성에 따른 혹은 index 삭제에 따른 전체 성능, 일부 성능 측정에 도움이 될 만한 feature가 아닌가 싶습니다.

Invisible index 생성
SQL> Create index invisible_index on table(column) invisible;

Invitible index 사용 정의
SQL> alter session set optimizer_use_invisible_indexes=true;

Invisible index를 visible로 변경
SQL> alter index invisible_index visible;

visible index를 invisible로 변경
SQL> alter index invisible_index invisible;





운영 중 spfile이 유실 되는 경우, 간편하게 recovery 할 수 있는 명령어가 oracle 11g에서 추가되었네요.

뭐 alert log file에 나온 parameter 정보나 show parameter 등으로도 만들 수 있지만 많이 귀찮죠.
(사실 spfile이나 init file 유실되는 건 본적은 없으나...)

create spfile from memory;
create spfile='/u01/oracle/app/oracle/product/11g/dbs/spfile_back.ora' from memory;







전통적인 Oracle 접속 방식인 "Dedicated Server"와 "Shared Server" 방식외에 Oracle 11g에서 DRCP (Database Resident Connection Pooling)라는 접속 방식이 추가 되었습니다.

Database resident connection pooling (DRCP) provides a connection pool in the database server for typical Web application usage scenarios where the application acquires a database connection, works on it for a relatively short duration, and then releases it.

메뉴얼을 보면 각각의 접속 방식에 소모되는 memory를 계산해 놓은 부분이 있는데, 요거 보면 적용할 만 하겠다 싶긴 합니다.

그러나 memory 사용량을 보면 혹할수도 있겠는데, 만약 concurrent가 5000이라고 가정 한다면,
DRCP의 경우는 100개만 접속 해 있고 나머지는 queue에 대기하고 있는 모양이겠죠?

shared server의 경우 100개만 떠있어도 100개의 shared server가 5000개의 세션을 cover 해주고 있으니,
DRCP와 dedicate/ shared server와 비교하는 것 자체가 사실 말이 안될 수 도 있습니다.

memory required for each session is 400 KB and the memory required for each server process is 4 MB. The pool size is 100 and the number of shared servers used is 100. If there are 5000 client connections, the memory used by each configuration is as follows:

 Dedicated Server
 Memory used = 5000 X (400 KB + 4 MB) = 22 GB
 Shared Server
 Memory used = 5000 X 400 KB + 100 X 4 MB = 2.5 GB
 Database Resident Connection Pooling
 Memory used = 100 X (400 KB + 4 MB) + (5000 X 35KB)= 615 MB

설정 방법도 별로 어렵지 않습니다. 서버단에서 process parameter 좀 늘려주고 다음 처럼 수행하고, client 단에서 tnsnaems.ora의 설정 부분에 SERVER를 POOLED라고만 정의하면 되네요. 

DRCP 설정 방법
SQL> exec dbms_connection_pool.configure_pool(maxsize=>10,inactivity_timeout=>60);
SQL> exec sys.dbms_connection_pool.start_pool();

Client 설정
DRCP =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = sample.com)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = POOLED)
      (SERVICE_NAME = orcl.sample.com)
    )
  )

딱히 테스트 해보고 올린 post가 아니니 잘못된 부분이 있으면 가차없이 알려주세요. ^^





오라클 11g release 1 documents library 입니다.

oracle 11g release 1 documents library

oracle 11g release 2 documents library



+ Recent posts