'2008/01/02'에 해당되는 글 4건

Log4J ....

Etc 2008/01/02 22:46

1. Log4J 기능

 

Log4J는 5개의 레벨로 메세지를 로깅할 수 있다.


debug : 완성된 어플리케이션에서는 출력되지 않아야 하며, 개발의 편의를 위한 디버깅 메세지를 쓰기위해 사용

info : 어플리케이션의 verbose 모드에서 출력될만한 메세지를 쓰기위해 사용

warn : 어플리케이션의 경고 메세지를 쓰기위해 사용

error : 어플리케이션이 돌아가기는 하나, 에러 메세지를 쓰기위해 사용

fatal : 어플리케이션이 비정상적으로 종료될 치명적인 메세지를 쓰기위해 사용


2. Log4J 설치


1. 파일다운로드 : http://logging.apache.org/site/binindex.cgi 


2. logging-log4j-1.2.14.zip 압축을 풀고 \logging-log4j-1.2.14\logging-log4j-1.2.14\dist\lib\log4j-1.2.14.jar 파일을 해당 어플리케이션의 \WEB-INF\lib\ 에 위치시킨다.


3. \logging-log4j-1.2.14\examples\log4j.properties 파일을 \WEB-INF\classes\ 에 위치시키고 수정하여 사용



3. Log4j.properties 설정


Log4j 를 설정하는 기본파일은 log4j.properties 이다.


Log4j를 설정하는 것은 Category(logger)Appender (목적지/대상/핸들러)를 더하고 각각의 Appender 에게 Layout(구성)을 저정하는 것이다.


하나의 Category는 하나 혹은 그 이상의 대상에 로그하도록 설정된다. 이 대상을 Appender 라고 부르며 한번의 로깅 호출로 콘솔, 텍스트파일, Html 파일, Xml 파일, 소켓등으로 로그메세지를 보낼 수 있다. 이러한 Appender 에는 ConsoleAppender, FileAppender, SMTPAppender ,SocketAppender, SyslogAppender 등이 있다.


Log4j는 날짜, 시간, 메세지 레벨, Java 클래스명, 메소드명 등의 정보를 Layout의 설정을 통해 로그 메세지에 추가할 수 있다.



4. Log4J 활용


** Layout 사용하기 


%m : 메세지 출력

%p : priority 출력

%r : 어플리케이션이 시작되어 로깅이벤트가 발생하는 시점까지의 경과시간을 밀리세컨드로 출력

%c : category 출력

%n : 개행문자 출력

%d : 로깅이벤트가 일어나 날짜 출력 ( 프로그램의 실행속도를 느리게 한다.)

        예) %d{HH:mm:ss} 또는 %d{dd MMMM yyyy HH:mm:ss}

%C : 호출자의 클래스명 출력

%M : 호출자의 메소드 출력

%F : 호출자의 파일 이름 출력



** Appender 사용하기

 

* ConsoleAppender 옵션

 

Threadhole=WARN : category 의 priority가 더 낮게 지정되어 있더라도 여기 명시된 priority 보다 낮은 메세지들은 로깅하지 않는다.

ImmediateFlush=true : 기본값은 true 로그메세지가 버퍼되지 않는다.

Target=System.err : 기본값은 System.out

 

* FileAppender 옵션

Threadhole=WARN : category 의 priority가 더 낮게 지정되어 있더라도 여기 명시된 priority 보다 낮은 메세지들은 로깅하지 않는다.

ImmediateFlush=true : 기본값은 true 로그메세지가 버퍼되지 않는다.

File=testlog.txt : 로깅할 파일명

Append=false : 기본값은 true이며, 파일끝에 추가하는 것을 의미한다.


* RollingFileAppender 옵션

Threadhole=WARN : category 의 priority가 더 낮게 지정되어 있더라도 여기 명시된 priority 보다 낮은 메세지들은 로깅하지 않는다.

ImmediateFlush=true : 기본값은 true 로그메세지가 버퍼되지 않는다.

File=testlog.txt : 로깅할 파일명

Append=false : 기본값은 true이며, 파일끝에 추가하는 것을 의미한다.

MaxFileSize=100KB : KB, MB, GB 의 단위를 사용, 지정한 크기에 도달하면 로그파일을 교체한다.

MaxBackupIndex=5 : 최대 5개의 백업 파일을 유지한다.


* DailyRollingFileAppend 옵션


Threadhole=WARN : category 의 priority가 더 낮게 지정되어 있더라도 여기 명시된 priority 보다 낮은 메세지들은 로깅하지 않는다.

ImmediateFlush=true : 기본값은 true 로그메세지가 버퍼되지 않는다.

File=testlog.txt : 로깅할 파일명

Append=false : 기본값은 true이며, 파일끝에 추가하는 것을 의미한다.

DatePattern='.'yyyy-mm : 매월 파일을 교체한다. 교체주기는 월, 주, 일, 시간, 분 별로 정할 수 있다.

 

 

 

-------------------------------------------------------------------------

-- * Log4j 설정파일 예제

--  두개의 Appender를 사용하여, 하나는 콘솔에, 하나는 파일에 로깅한다.

-------------------------------------------------------------------------


# root category 의 레벨 (priority)를 DEBUG로 설정한다.

log4j.rootCategory=DEBUG, stdout, file


#log4j를 설정하는 상세 정보 출력여부 (true/false)
log4j.debug=false


#---------------------------------
# 첫번째 appender : 콘솔에 로깅
#---------------------------------
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.ImmediateFlush=true
log4j.appender.stdout.Target=System.err


# 출력 Layout 설정 : 호출하는 파일명출력

log4j.appender.stdout.layout.ConversionPattern=[%p] (%F) - %m%n


#---------------------------------
# 두번째 appender : 파일에 로깅
#---------------------------------
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.ImmediateFlush=true
log4j.appender.file.File=logs/testlog.txt
log4j.appender.file.Append=true


# 파일명 패턴
log4j.appender.file.DatePattern ='.'yyyy-MM-dd


# 출력 Layout 설정 : 호출하는 시간, 파일명등 출력
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%d{HH:mm:ss}] [%p] (%F) - %m%n



출처 ==== 네이버 블로그~~~


Posted by HelolS
TAG Log4J

출처 : http://wireless.moba.co.kr/general/lecture/unix/lec4-3.htm


시스템 프로세스 관리


유닉스 시스템 사용자라면 누구나 현재 수행되고 있는 프로세스들이 무엇이고 어떤 상태인지 보고 싶은 적이 있을 것이다. 여기서는 수행되고있는 프로세스들을 어떻게 볼 수 있으며, 이들을 제어하는 방법에 대해 설명하고, 이러한 반복적인 작업을 자동화하는 방법에 대해서 설명한다.

프로세스들의 속성을 보기 위한 명령어로는 ps 와 pgrep 을 사용하고, 프로세스를 끝내는데 사용되는 명령어로는 kill 과 pkill 이 있다

ps와 kill 사용하기

ps는 현재 활동하고 있는 프로세스들의 정보를 보여주는데 사용된다. 많은 관리자들은 kill 을 사용해 프로세스를 죽이기 위해서는 프로세스의 id(PID)를 알아야 하기 때문에 ps 를 사용해서 PID를 알아낸다.

ps에는 많은 옵션들이 있어 프로세스의 정보를 여러 원하는 형태로 출력되도록 사용이 가능하다. 사용 가능한 옵션들은 아래와 같다.

-A-e 는 모든 프로세스를 출력
-a는 터미널과 관련되지 않은 프로세스와 프로세스 그룹 리더를 제외한 모든 프로세스를 출력
-g프로세스그룹ID 는 특정 프로세스그룹의 프로세스들을 출력
-G그룹ID 는 특정 그룹에 속한 user 들의 프로세스만 출력
-f 는 full 리스트 형식으로 출력
-l 는 long 리스트 형식으로 출력
-j 는 프로세스의 세션ID 와 프로세스 그룹ID 를 출력
-t 터미널디바이스패스 는 특정 터미널 디바이스 패스와 연관된 프로세스들만 출력
-u USER ID 는 특정 user 의 프로세스만 출력

ps 사용 예를 보자.
옵션 없이 ps명령어만 사용한 기본 출력형태는 아래와 같다.

$ ps

PID TTY TIME CMD
10071 pts/5 0:00 bash



여기서 나타나는 PID 는 프로세스의 ID 를 나타내고 TTY는 터미널 디바이스를, TIME 는 수행시간을 CMD 는 프로세스가 수행하는 프로그램이나 명령어를 나타낸다.
몇 가지 사용 예를 더 살펴보자.

$ps -tpts/5

PID TTY TIME CMD
441 pts/3 0:01 dtsessio
431 pts/3 0:00 bash
440 pts/3 0:00 ttsessio
428 pts/3 0:00 sdt_shel



위의 명령은 터미널 디바이스 pts/5 에 관련된 프로세스들의 목록을 보여준다.

$ps -f -tpts/3

UID PID PPID C STIME TTY TIME CMD
root 441 431 0 Nov 20 pts/3 0:01 /usr/dt/bin/dtsession
root 431 428 0 Nov 20 pts/3 0:00 -bash -c
root 440 1 0 Nov 20 pts/3 0:00 /usr/dt/bin/ttsession
root 428 384 0 Nov 20 pts/3 0:00 /usr/dt/bin/sdt_shell



-f 옵션을 사용한 full 리스트는 위와 같이 출력되며 여기서의 UID는 user ID 이고, PPID 는 parent PID 를, C는 소모한 프로세서의 이용시간을 나타내고 STIME 은 프로세스 시작날짜를 나타내 준다.

kill 명령어를 사용하면 ps를 통해서 알아낸 PID 를 가지고 프로세스에게 시그널을 보내 프로세스를 중지시킬 수 있다. 사용 방법은 kill ?signal값 PID 와 같이 사용한다.

kill 명령어를 사용해서 프로세스에게 보낼 수 있는 시그널의 종류는 다음과 같고, 모든 시그널을 받았을 때 프로세스는 기본적으로 프로세스를 끝내는 것으로서 시그널에 응답한다.

Symbol          Value   Description

SIGHUP 1 Hangup
SIGINT 2 Interrupt
SIGKILL 9 kill
SIGTERM 15 Terminate
SIGUSR1 16 User signal 1
SIGUSR2 17 User signal 2



kill 명령어로 프로세스에게 시그널을 보낼 때는 시그널의 symbol 이나 Value 둘 다 사용 가능하다. 아래의 예는 둘 다 같은 결과를 가진다.

$ kill -SIGKILL 4220 4224 4229
4229 Killed
4224 Killed
4220 Killed

$kill -9 4220 4224 4229
4229 Killed
4224 Killed
4220 Killed



pgrep 과 pkill 사용하기

ps 와 kill 외에 프로세스를 보고 프로세스에게 시그널을 보내는 명령어로 pgrep 과 pkill 이 있다. 이 명령어 들은 UID 나 GID 같은 특정 attribute 들에 속하는 프로세스들의 목록을 볼 수 있을 뿐 아니라 regular expression을 사용해서 특정패턴을 가지고 특정 프로세스들을 보거나 종료 시킬 수 있다.

예를 들면 ps를 사용해서 adimintool 을 실행하고 있는 프로세스를 찾기 위해서는 다음과 같이 한다.

$ ps -eaf | grep admintool
root 2898 1096 0 Sep 04 pts/7 0:02 admintool



이것을 pgrep을 사용하면 아래 같이 간단하다.

$ pgrep adm*
2898



다만 pgrep 을 사용하면 PID 만이 출력된다. 프로그램의 이름까지 출력하고자 할 경우 -l 옵션을 사용하면 PID 와 프로그램이름을 같이 볼 수 있다.

이 외에도 pgrep 에서 사용되는 옵션으로는 -f 하면 패턴을 프로그램의 이름에서만 매치시키는 것이 아니라 모든 argument 에서 패턴과 매치되는 프로세스들을 출력시켜준다.

-n은 매치되는 프로세스들 중에서 가장 최근에 생긴 프로세스 하나만을 보여주고, -x는 패턴과 정확히 매치된 프로세스만 보여준다.

특정 ID 를 가진 프로세스를 찾기 위해서 사용하는 옵션들은 ?g(Process Group ID), -G(Real Group ID), -P(Parent Process ID), -s(Process Session ID), -t(Terminal Device Path), -U(Real User ID) 등이 있다.

그리고 pgrep 이 PID를 출력할 때는 디폴트로 한 줄에 하나의 PID 를 출력한다. 많은 프로세스들이 출력될 때는 한꺼번에 화면이 빠르게 넘어가기 때문에 보기가 불편할 것이다. 이럴때 -d 옵션을 사용하면 유용하다. d옵션 뒤에 표시된 것을 구분자로 해서 PID 가 출력된다.

$ pgrep -d ‘, ‘ -u dla
781, 782, 910, 913



pkill 명령어도 pgrep 명령어와 사용법이 유사하다. 다만 PID 를 출력해주는 대신에 매치되는 프로세스들을 SIGTERM(15) 를 사용해서 종료시켜 준다. SIGTERM 대신에 특정 signal을 명시해서 사용해도 무방하다.

사용되는 옵션들은 pgrep 과 같다. 다음은 user ID 가 dla 인 프로세스들을 종료시켜준다.

$ pkill -KILL -u dla



cron 사용하기

시스템 관리자와 사용자들은 주기적으로 일어나는 작업에 대해서 매일매일 수동으로 수행하기 보다는 때가 되면 자동으로 원하는 작업이 정기적으로 실행되길 원한적이 있을 것이다.

cron 은 미래에 실행할 작업을 주기적으로 수행하도록 스케줄할 수 있게 해준다.
cron은 시스템이 부팅될 때 시작되는 데몬이다. cron 데몬은 crontab 파일을 참조해서 파일 안에 명시된 작업을 규정된 시간에 수행한다. crontab 파일은 /var/spool/cron/crontabs 디렉토리에서 읽어서 수행한다.
다른 시스템과 마찬가지로 cron 의 행위를 setting 할 수 있는데, 이들 setting 들은 /etc/default/cron 파일에 명시되어 있다.

cron 명령은 디폴트로 로그파일을 기록하도록 아래와 같이 /etc/default/cron 파일에 설정되어 있다.

    CRONLOG=YES

이것이 설정되어 있으면 cron 의 모든 활동에 대한 로그를 /var/cron/log 파일안에 저장한다. log를 기록하고 싶지 않으면 YES 를 NO로 변경하면 된다.

이 외에도 /etc/default/cron 파일에 설정할 수 있는 내용은 cron 작업들의 PATH 와 SUPATH 를 아래와 같이 setting 시킬 수 있다.

PATH=/usr/bin:/usr/ucb:
SUPATH=/usr/sbin:/usr/bin:



cron 데몬은 /var/spool/cron/crontabs/ 아래의 파일들을 읽어서 예약해놓은 작업들을 실행한다. 이 디렉토리에는 시스템과 유저의 파일들을 포함하고 있는데, 파일의 이름은 유저의 이름과 동일하게 생성된다.

다음은 default 로 생성된 root 의 crontab 파일이다.

10 3 * * 0,4 /etc/cron.d/logchecker
10 3 * * 0 /usr/lib/newsyslog
15 3 * * 0 /usr/lib/fs/nfs/nfsfind
1 2 * * * [ -x /usr/sbin/rtc ] && /usr/sbin/rtc -c > /dev/null 2>&1
30 3 * * * [ -x /usr/lib/gss/gsscred_clean ] && /usr/lib/gss/gsscred_clean



파일 안에는 space 또는 tab으로 분리된 6개의 엔트리를 가진다. 각 엔트리와 해당 값은 다음과 같다.

    분(0-59), 시간(0-23), 일(1-31), 달(1-12), 요일(0-6: 일요일=0), 명령어

하나의 엔트리에는 2개 이상의 값을 표현할 수가 있다. 만약 1,2,3 월에 계속 하고 싶은 작업이라면 달에 해당 하는 값을 1-3으로 표시하거나, 컴마로 구분해서 1,2,3 과 같이 표현하는 것도 가능하다. * 는 모든 값에 다 해당한다는 표현이다.

그럼 이제부터 자신의 작업을 스케쥴링 해보자.

만약 guest 라는 user account 를 가진 사람이 일요일마다 12시 정각에 자신의 홈 디렉토리에 있는 test 명령을 실행 하도록 나의 crontab 파일을 만들어보자.

    $crontab -l

하고 입력하면 현재 세팅되어 있는 나의 crontab 파일의 내용이 출력된다.
물론 아무 내용이 없다면 출력되지 않을 것이다.
그럼 위의 작업을 스케쥴하려면

    $crontab

을 하고 나면 입력이 가능 하도록 되며 여기에 작업내용을 입력한다.

    0 12 * * 0 /home/guest/test

라고 입력하고 Ctrl+D를 입력하면 나의 /var/spool/cron/crontabs/guest 파일이 생성된다.

이 파일은 root 만이 볼 수 있고 수정할 수 있다.
내 crontab 파일을 수정하기 위해서는 아래와 같이 한다.

$EDITOR=vi
$export EDITOR
$crontab -e



위와 같이 실행하고나면 사용자의 crontab 파일이 vi 편집기로 열린다. 여기서 수정을 하면 된다.

이렇게 작업을 예약하고 나면 알아서 cron 데몬이 해당되는 시간에 예약된 작업들을 수행시켜 준다. 만약 수행할 결과의 output 이 있다면 사용자에게 메일로 전달된다.

-r 옵션을 사용하면 사용자의 crontab 파일이 삭제된다.

crontab 파일에 접근허가는 /etc/cron.d/ 아래에 있는 cron.allow 와 cron.deny 2개의 파일로 컨트롤할 수 있다. 각 파일들에는 접근을 허락하기위한 또는 거절하기 위한 user account 이름을 한 줄에 하나씩 열거한 텍스트가 들어있다.

처음 시스템을 설정하고 나면 기본적으로 cron.allow 파일은 없고 cron.deny 파일만 존재한다.

at 사용하기

이 명령어는 특정시간에 명령 혹은 스크립트를 수행하게 하며, 단지 한번 수행된다는 점이 crontab 파일과는 다르다.

    $ at [-m] [-r 작업] 시각 [날짜]

-m 옵션을 사용하면 작업이 끝난후에 사용자에게 메일을 보내준다. -r 옵션은 at명령어로 예약해 놓은 작업큐에서 작업을 삭제하기 위해 사용한다. 시각은 아래와 같이 여러 방법으로 규정될 수 있다.

$at now
$at 10am
$at 2pm
$at noon
$at 3pm + 1 week
$at 2am jan 24
$at 1400 tomorrow



간단한 예로 12시에 ls 를 수행하도록 작업을 예약하기 위해서는

$at 12:00
at> ls
at> Ctrl +D 입력 #at 종료
commands will be executed using /bin/bash
job 975034800.a at Fri Nov 24 12:00:00 2000



이렇게 하면 975034800.a 라는 작업이 큐에 쌓이게 된다. 만일 오늘이 12시가 지났다면 다음날 12시에 수행하도록 작업이 설정된다. 큐의 내용을 확인하려면 atq 명령어를 사용한다.

$atq

Rank Execution Date Owner Job Queue Job Name
1st Nov 24, 2000 12:00 smdoo 975034800.a a stdin



큐의 작업을 삭제하려면 at -r 작업번호를 입력한다.

    $at -r 975034800.a

at 명령어도 역시 /usr/lib/cron/at.allow 와 /usr/lib/cron/at.deny 파일들에 의해서 접근을 컨트롤 할 수 있다.

솔라리스 프로세스의 핵심적인 특징중의 하나는 /proc 파일시스템으로 마운트되는 프로세스 파일 시스템이다. /proc 파일 시스템에는 PID를 이름으로 가진 현재 활동중인 프로세스의 이미지를 담고 있다. 예를 들면, 먼저 guest 라는 사용자의 프로세스에서 현재 shell 프로세스의 이미지를 살펴보자.

$ps ?aef |grep guest

guest 25909 25904 0 10:55:48 pts/1 0:00 -bash
guest 25991 25909 0 11:18:56 pts/1 0:00 grep guest



여기서 bash 의 PID 는 25909 이다. 이 프로세스의 이미지를 보기위해서는 /proc/25909 디렉토리로 가면 볼 수 있다.

$cd /proc/25909

$ ls ?ltotal 5003
-rw------- 1 guest staff 2531328 Nov 24 10:55 as
-r-------- 1 guest staff 152 Nov 24 10:55 auxv
-r-------- 1 guest staff 32 Nov 24 10:55 cred
--w------- 1 guest staff 0 Nov 24 10:55 ctl
lr-x------ 1 guest staff 0 Nov 24 10:55 cwd ->
dr-x------ 2 guest staff 8208 Nov 24 10:55 fd
-r--r--r-- 1 guest staff 120 Nov 24 10:55 lpsinfo
-r-------- 1 guest staff 912 Nov 24 10:55 lstatus
-r--r--r-- 1 guest staff 536 Nov 24 10:55 lusage
dr-xr-xr-x 3 guest staff 48 Nov 24 10:55 lwp
-r-------- 1 guest staff 2304 Nov 24 10:55 map
dr-x------ 2 guest staff 544 Nov 24 10:55 object
-r-------- 1 guest staff 2752 Nov 24 10:55 pagedata
-r--r--r-- 1 guest staff 336 Nov 24 10:55 psinfo
-r-------- 1 guest staff 2304 Nov 24 10:55 rmap
lr-x------ 1 guest staff 0 Nov 24 10:55 root ->
-r-------- 1 guest staff 1440 Nov 24 10:55 sigact
-r-------- 1 guest staff 1232 Nov 24 10:55 status
-r--r--r-- 1 guest staff 256 Nov 24 10:55 usage
-r-------- 1 guest staff 0 Nov 24 10:55 watch
-r-------- 1 guest staff 3648 Nov 24 10:55 xmap



이 디렉토리에는 프로세스의 상태 정보 등을 포함하고 있는 서브디렉토리들을 포함하고 있다. 서브디렉토리안에 있는 정보를 해석하기위한 tool 로 proc tool이 있다. 이것은 각 프로세스의 특징들을 출력시켜주는 역할을 한다.

proc tool 사용하기

proc tool들은 /proc 파일시스템 안에 있는 데이터들을 다루기 위한 것이다. 이 툴에 있는 유틸리티들로는 pflags, pcred, pfiles, pldd, pmap, psig, pstack, pstop, ptime, ptree, pwait, pwdx 가 있고, 모든 유틸리티들은 argument로 PID 를 사용한다.
각각이 하는 일이 무엇인지 하나씩 살펴보도록 하자.
pflags는 해당 PID 의 자세한 데이터 모델과, flag에 대한 정보를 보여준다.
위의 bash 쉘에 대한 사용 예를 보면 아래와 같다.

$ pflags 25909

25909: -bash
data model = _ILP32 flags = PR_ORPHAN
/1: flags = PR_PCINVAL
sigmask = 0x00020002,0x00000000
$pcred 25909
26838: e/r/suid=3001 e/r/sgid=10



pcred 는 수행되는 프로세스의 effective, real, saved UID 와 GID 를 보여준다. pmap 은 프로세스의 메모리 세그먼트 사이즈와 address space 를 보여준다. 그리고 pldd 명령어는 각 프로세스에 링크된 dynamic libraries 를 보여준다.

$pmap 25909

25909: -bash
00010000 432K read/exec /usr/bin/bash
0008A000 80K read/write/exec /usr/bin/bash
0009E000 152K read/write/exec [ heap ]
FF150000 16K read/exec /usr/lib/locale/en_US.ISO8859-1/en_US.ISO8852
FF162000 16K read/write/exec /usr/lib/locale/en_US.ISO8859-1/en_US.ISO8852
FF170000 16K read/exec /usr/platform/sun4u/lib/libc_psr.so.1
FF180000 664K read/exec /usr/lib/libc.so.1
FF236000 24K read/write/exec /usr/lib/libc.so.1

$pldd 25909
26838: -bash
/usr/lib/libcurses.so.1
/usr/lib/libsocket.so.1
/usr/lib/libnsl.so.1
/usr/lib/libdl.so.1
/usr/lib/libc.so.1
/usr/lib/libmp.so.2
/usr/platform/sun4u/lib/libc_psr.so.1
/usr/lib/locale/en_US.ISO8859-1/en_US.ISO8859-1.so.2



pfile은 proc tool 중에 많이 쓰이는 명령어 중 하나이다. 이것의 역할은 각 프로세스의 모든 open 파일들을 출력해 준다. 출력내용은 파일이 저장되어 있는 파티션의 inode 번호, UID, GID, 접근허가 정보 등이다.

$pfiles 25909

25909: -bash
Current rlimit: 256 file descriptors
0: S_IFCHR mode:0620 dev:32,0 ino:320235 uid:3001 gid:7 rdev:24,1
O_RDWR
1: S_IFCHR mode:0620 dev:32,0 ino:320235 uid:3001 gid:7 rdev:24,1
O_RDWR
2: S_IFCHR mode:0620 dev:32,0 ino:320235 uid:3001 gid:7 rdev:24,1
O_RDWR
3: S_IFDOOR mode:0444 dev:188,0 ino:1793 uid:0 gid:0 size:0
O_RDONLY|O_LARGEFILE FD_CLOEXEC door to nscd[225]
255: S_IFCHR mode:0620 dev:32,0 ino:320235 uid:3001 gid:7 rdev:24,1
O_RDWR FD_CLOEXEC



이 외에도 psig 는 각 프로세스의 signal action 리스트를 보여주고, pgrep 과 pkill 은 앞에서 언급했던 것처럼 프로세스의 목록을 보고 프로세스에게 시그널을 보내는 역할을 해준다. prun 은 process 를 running 시키고, pstop 은 kill 명령어와 같은 유사한 방법으로 프로세스를 중지시켜준다.

pstack 은 프로세스 thread 의 stack trace 를 보여주고, ptree 는 프로세스가 생성된 tree 를 process ID 를 통해 나타내준다.

프로세스의 시간 정보를 보기위해 사용되는 명령어로는 ptime 이 있고, pwait 는 프로세스가 끝나기를 기다리도록 하는 명령어이고, pwdx 는 프로세스의 working directory를 보여준다.

lsof 사용하기

lsof 는 “list open file”을 나타낸다. 이 명령어는 프로세스에 의해 현재 open된 파일들의 정보를 보여준다. 이 명렁어는 Solaris에 포함되어 있지는 않으나, ftp://vic.cc.purdue.edu/pub/tools/unix/lsof에서 최신 버전을 다운 받아서 사용할 수 있다. lsof 가 얼마나 유용한지에 관한 것은 얼마나 파일과 프로세스에 관련된 문제들에 많이 직면하는지에 달려 있다.

관리자들은 프로세스가 현재 사용하고 있는 파일이 무엇이고, 특정 디렉토리에서 어떤 파일들을 사용하는지 알고 싶을 때가 있을 것이다. 만약 어떤 파일이 다른 프로세스에 의해 사용되고 있어서 lock 되었을 경우, 그 파일을 사용하는 다른 프로세스는 파일을 사용할 수 없을 것이다. 후자의 프로세스를 수행시키고자 할 경우 전자의 프로세스의 PID 를 찾아서 이를 중지시킨 후 파일을 사용할 수 있을 것이다.

lsof 를 사용하면 디렉토리안에 파일들이 어떤 프로세스에 의해 사용되고 있는지 알 수 있다. 다음과 같이하면 /tmp 파일시스템에 있는 파일들이 어떤 프로세스에 의해 사용되는지 볼 수 있다.

    $ lsof /tmp

파일시스템을 마운트하는 제한사항 중에 하나는 만일 파일시스템에 open 된 파일이 존재한다면 이 파일시스템은 unmount 시킬 수 없을 것이다. 그 이유는 파일시스템이 unmount 된다면 파일에 대한 변화된 정보를 기록할 수 없기 때문이다.

파일시스템을 unmount 하려고 했다가 실패를 한 경우, lsof 를 사용해 파일시스템 안의 파일중 open 된 파일의 리스트를 얻어서 해당 프로세스를 중지시키면 파일시스템을 무사히 unmount 시킬 수 있다.

Posted by HelolS

Materialized View

oradata 2008/01/02 14:20

펌 : http://blog.naver.com/khlee1000/40023271788

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
Subject:  Materialized View
Type:     WHITE PAPER
Status:   PUBLISHED
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
 
◎ 이 문서는 Materialized View에 대해 8i부터 10g까지의 자료를 정리한 것이다.
 
◎ 목차:
   1. Materialized View
   2. Materialized View 관련 Initialization 파라미터
   3. Materialized View 사용에 필요한 권한
   4. Query Rewrite에서 Materialized View 사용 여부 판단 알고리즘
   5. Materialized View와 Integrity Constraints
   6. Query Rewrite와 Hint 사용
   7. Three Types of Materialized Views
   8. Materialized View Log 의 구조 (WITH ROWID, PRIMARY KEY 사용)
   9. Materialized View의 문법
  10. Materialized View 의 Index
  11. Materialized View를 만드는 방법 (사용예제)
  12. Materialized View에서 Index Organize Table을 이용하기 (8.1.6 이상)
  13. Materialized View의 On Commit Refresh 기능 (8.1.6 이상)
  14. Materialized View 생성 시 ORA-12054 ERROR 해결 방법 (8.1.6 이상)
  15. Materialized View 에서 Order By 절 사용하기 (8.1.7 이상)
  16. Materialized View를 Refresh 하는 방법
  17. Materialized View와 관련된 시스템 딕셔너리
  18. 진단을 위한 DBMS_MVIEW.EXPLAIN_REWRITE / EXPLAIN_MVIEW 사용법 (9.0.2 이상)
  19. Nested Materialized Views
 
 
 
1. Materialized View
 
◎ Oracle 8i에서의 "MATERIALIZED VIEW" 는 "SNAPSHOT" 와 SYNONYM 으로 생각 하면 가장 좋을 것 같다. 
   이는 대용량의 DATABASE 에서 SUM 과 같은 AGGREGATE FUNCTION 사용 시 값 비싼 COST 를 줄이는 데
   사용하기에 적합한데 이는 REPLICATE 가 가능하여 SNAPSHOT 처럼 사용이 가능함을 의미한다.
 
◎ Materialized View(이하 MVIEW)는 DW 환경이나, replication 환경에 유용한 기능으로, inner-join,
   outer-join, equi-join 등 각종 view를 수동으로 갱신하거나, 주기적으로 자동 갱신을 할 수 있게 해 준다.
 
◎ 원격 데이터베이스의 테이블이 포함된 MVIEW는 양방향 replication을 지원한다. 또한 MVIEW는 사용자에게는
   투명하게 cost optimization에 기반을 둔 qurey rewrite 기능을 제공한다.
 
◎ Query rewrite란 table과 view들에 대한 연산으로 이루어진 SQL 문장이 해당 table들에 기반해서 정의된
   materialized view에 대한 연산으로 변경되는 것을 말한다. 이러한 변경은 Optimizer에 의해 내부적으로
   수행되기 때문에 일반 사용자나 application은 materialized view의 존재 여부를 인식하지 않아도 된다.
 
◎ Query rewrite는 cost-based optimization 모드에서만 가능하다. 따라서 Materialized View를 만들기 위해선
   해당 Table이 반드시 Analyze 되어 있어야 한다.
 
◎ Query rewrite 기능을 제공하기 위해 Oracle 에서는 Dimension이라는 객체를 추가 했는데,
   Dimension 객체는 대용량 데이터에 대한 질의를 집계성 데이터에 대한 질의로 자동 변환 해 주는 기능을 제공해 준다.
 
◎ MVIEW는 질의 실행을 할 때마다 매번 대량의 join이나, Aggregation 연산(예: SUM, COUNT 등)을 수행하지 않고,
   미리 계산된 값을 질의하기 때문에 성능 향상을 가져올 수 있으며, optimizer는 MVIEW가 어느때 사용되는 것이
   적절할지를 판단할 수 있게 설계되었다.
 
◎ Query rewrite는 사용자에는 투명하다. 만약 환경이 적절히 셋업 되어 있다면, 대량 대이터에 대한
   복잡한 질의 응답 속도를 획기적으로 개선할 수 있게 한다.
 
 
 
2. Materialized View 관련 Initialization 파라미터
 
◎ MVIEW와 관련된 파라미터 목록은 다음과 같다.
   - optimizer_mode
   - query_rewrite_enabled
   - query_rewrite_integrity
   - compatible
 
◎ 다음은 파라미터에 대한 설명이다.
  1) optimizer_mode
     - Query Rewrite 기능을 사용하기 위해서는 init.ora 파일의 optimizer mode값은 "ALL_ROWS"나
       "FIRST_ROWS"로 지정하거나, "CHOOSE"인 상태에서 모든 테이블을 ANALYZE 시켜 두어야 한다.
   
  2) query_rewrite_enabled
     - 파라미터 query_rewrite_enabled 의 값은 "TRUE"로 지정한다.
   
  3) query_rewrite_integrity
     - 파라미터 query_rewrite_integrity 는 선택적으로 지정할 수 있는 파라미터이지만,
       "STALE_TOLERATED", "TRUSTED", 또는 "ENFORCED" 으로 지정되어야 한다.
 
     - 이 파라미터는 query rewrite의 정확성을 제어 하는 파라미터이다.

     - 각각의 의미는 다음과 같다
       ☞ TRUSTED : optimizer에서 MVIEW의 데이터가 정확하다고 간주하고 질의 수행. Integrity 확인을 하지않음.
       ☞ ENFORCED: query_rewrite_integrity 의 기본값으로, 사용자가 integrity constraint를 확인하여야 한다.
                    MVIEW는 fresh한 데이터를 포함하여야 한다.
       ☞ STALE_TOLERATED : Optimizer에서 데이터가 stale 상태이거나 fresh 상태인 경우 모두 MVIEW 사용
 
 
 
3. Materialized View 사용에 필요한 권한
                        
◎ MVIEW를 사용하기 위한 권한은 base 테이블에 대한 사용자의 권한에 달려있다.
   두개의 중요한 시스템 권한은 다음과 같다.
   - grant rewrite
   - grant global rewrite
 
◎ 다음은 두개의 중요한 시스템 권한에 대한 설명이다.
  1) grant rewrite
     - MVIEW의 base table이 모두 사용자 자신의 테이블일 경우, 자신이 선언한 MVIWE 사용 가능.
   
  2) grant global rewrite
     - 사용자가 어느 schema에 속한 MVIEW라도 사용 가능.
   
◎ MVIEW 사용에 필요한 권한이 충족된 경우 다음 조건을 만족하여야 한다.
   a.  세션에 query rewrite 기능이 enable 되어 있음.
   b.  MVIWE 자체가 enable 되어 있음.
   c.  integrity level이 적절히 셋업 되어 있음.
   d.  MVIEW에 데이터가 존재함.
 
 
4. Query Rewrite에서 Materialized View 사용 여부 판단 알고리즘
 
1) Full SQL Text Match
   - 질의의 select 문장과 MVIEW를 만들때 사용한 select 문장 비교
 
2) Partial SQL Text Match
   - Full SQL Text Match가 실패할 경우 select 문장의 from 절 이하의
     내용이 MVIEW를 만들때 사용한 내용과 일치하는지 비교
 
3) Generla Query Rewrite Method
   - 1, 2 항에서 실패할 경우, optimizer에서 MVIEW 사용 가능 여부를 판단.
   - 필요한 데이터가 MVIWE에서 제공하는 것 보다 적거나, 많거나, 변환 가능
     한지를 판단하고, MVIWE 데이터가 충분한지 여부를 joing compatibility,
     grouping compatibility, aggregate compatibility 등을 확인하여 판단
 
 
 
5. Materialized View와 Integrity Constraints
 
◎ MVW는 DW 환경에서 유용한데, 대부분의 DW는 integrity constraint를 사용하지 않는다.
   즉 DW는 원천 데이터에서 integrity가 보장되었다고 간주한다.
 
◎ 다른 한편으로 integrity constraint는 query rewrite에 유용하다.
   이 모순되는 사항은 NOVALIDATE 와 RELY 옵션을 이용해 조율을 맞추어야 한다.
 
◎ query rewrite와 integrity constraint의 연관 관계
  1) query_rewrite_enabled = enforced
    - 데이터베이스의 constarint는 validate 상태로 두어야 한다.
 
  2) query_rewrite_enabled = stale_tolerated | trusted
    - 데이터베이스의 constraint를 nonvalidate, rely로 지정 해 준다.
 
 
 
6. Query Rewrite와 Hint 사용
 
◎ Index 관련 Hint를 사용하는 것 처럼, query rewite 관련 Hint를  사용하여 제어할 수 있다.
   - NOREWRITE :  Select /*+ NOREWRITE */...
   - REWRITE   :  Select /*+ REWRITE(MView_Name) */...
 
 
 
7. Three Types of Materialized Views
 
1) Materialized Aggregate View (MA-View)  
  - One Table
  - Aggregation (Sum, Avg...)
  - Example:
    create materialized view MA
    build immediate
    enable query rewrite
    refresh on demand
    as
    select g_no, sum(amount), count(amount), count(*)
    from fact -- One Table
    group by g_no;
 
   
  
2) Materialized Join View (MJ-View)
  - Many Tables
  - inner/outer join (join index)
  - no aggregates
  - Rowids from base tables in MV for incremental refresh
  - Example:
    create materialized view MAJ
    build immediate
    enable query rewrite
    refresh on demand
    as
    select f.g_no, f.amount, t.t_day, f.rowid f_rid
    from fact f, time t
    where f.t_no = t.t_no;
 
   
  
3) Materialized Aggregate Join View (MAJ-View)  
  - Many Tables
  - inner/outer join (join index)
  - Aggregation (Sum, Avg...)
  - Example:
   
create materialized view MAJ
    build immediate
    enable query rewrite
    refresh on demand
    as
    select g_no, sum(amount), count(amount), count(*), t_day
    from fact, time
    where f.t_no = t.t_no
    group by g_no, t_day;
 
 
 
8. Materialized View Log 의 구조 (WITH ROWID, PRIMARY KEY 사용)
 
◎ 우리가 Materialized View Log를 생성하면 Schema에는 mlog$_<master_table_name> 구조의
   Log Table이 생성이 된다.
 
  - Oracle은 이 Log에 변화되는 사항을 반영하게 된다. 그리고 Fast Refresh가 되면 이 Log의
    데이터를 Materialized View에 반영하게 된다.
 
  - 다음의 문장으로 확인을 할 수 있다.
 
    select log_owner, master, log_table, rowids, primary_key
    from dba_mview_logs;
 
    LOG_OWNER       MASTER     LOG_TABLE   ROWIDS    PRIMARY_KEY
    --------------- ---------- ----------- --------- -----------
    SCOTT           DEPT       MLOG$_DEPT  NO        YES
 
 
◎ Log를 생성하기 위한 문법 구조
 
   CREATE  MATERIALIZED  VIEW  LOG  ON <Master_Table_Name>
   TABLESPACE  <Tablespace_name>
   PCTFREE <Percent_Of_Free_Space>
   WITH [ ROWID | PRIMARY KEY ] , [ SEQUENCE ]
   INCLUDING NEW VALUES ;
 
  - WITH 절의 사용 예
    1) WITH ROWID
     SQL> create materialized view log on fnd_user with rowid including new values;
 
    2) WITH ROWID(Col1, ... , ColN)
     SQL> create materialized view log on fnd_user with rowid(user_id, user_name)  
        2  including new values;
 
    3) WITH ROWID, SEQUENCE(Col1, ... , ColN)
     SQL> create materialized view log on fnd_user with rowid, sequence(user_id, user_name)
        2   including new values;
 
    4) WITH ROWID, PRIMARY KEY
     SQL> create materialized view log on wf_in with rowid, primary key  including new values;
 
    5) WITH PRIMARY KEY
     SQL> create materialized view log on wf_in with primary key  including new values;
 
    6) WITH PRIMARY KEY, SEQUENCE(Col1, ... , ColN)
     SQL> create materialized view log on wf_in with primary key, sequence(corrid)
        2  including new values;
 
※ 주의: WITH ROWID(Col1, ... , ColN), SEQUENCE(Col1, ... , ColN) 의 문장은 가능하지 않다.
 
※ 주의:WITH ROWID(Col1, ... , ColN) 보다는 WITH ROWID, SEQUENCE(Col1, ... , ColN) 의 문장써라.
- WITH ROWID(Col1, ... , ColN) 와 WITH ROWID, SEQUENCE(Col1, ... , ColN)의 차이
  ☞ WITH ROWID(Col1, ... , ColN)는 순서가 부여되지 않는다.
  ☞ WITH ROWID, SEQUENCE(Col1, ... , ColN)는 SEQUENCE에 의해 컬럼의 순서가 부여 된다.
     이는 나중에 Fast Refresh를 하기 위해 필요할 때가 있다.. 따라서 두번째 방법을 사용하라.  
  
 
◎ Log를 생성시 Table의 구조..
 
  1) ROWID를 가지고 Log를 생성할 때
 
   SQL> create materialized view log on fnd_user with rowid including new values;
   SQL> desc mlog$_fnd_user
    Name                            Null?    Type
    ------------------------------- -------- ----
    M_ROW$$                                  VARCHAR2(255)
    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on fnd_user;
 
 
  2) Primary Key 를 가지고 Log를 생성할 때
   SQL> create materialized view log on wf_in with primary key including new values ;    SQL> desc mlog$_wf_in
    Name                            Null?    Type
    ------------------------------- -------- ----
    MSGID                                    RAW(16)
    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on wf_in; 
 
  3) ROWID와 NON-Primary Key 를 가지고 Log를 생성할 때
   SQL> create materialized view log on fnd_user with rowid, sequence(user_id, user_name)
      2 including new values ;    SQL> desc mlog$_fnd_user
    Name                            Null?    Type
    ------------------------------- -------- ----
    USER_ID                                  NUMBER(15)
    USER_NAME                                VARCHAR2(100)
    M_ROW$$                                  VARCHAR2(255)
    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on fnd_user; 
 
   
  4) ROWID와 Primary Key 를 가지고 Log를 생성할 때
   SQL> create materialized view log on wf_in with rowid, Primary Key including new values ;    SQL> desc mlog$_wf_in
    Name                            Null?    Type
    ------------------------------- -------- ----
    MSGID                                    RAW(16)
    M_ROW$$                                  VARCHAR2(255)

    SNAPTIME$$                               DATE
    DMLTYPE$$                                VARCHAR2(1)
    OLD_NEW$$                                VARCHAR2(1)
    CHANGE_VECTOR$$                          RAW(255)
   SQL> drop materialized view log on wf_in;
 
 
 
9. Materialized View의 문법
 
◎ 문법 :
 
   CREATE  MATERIALIZED  VIEW  <View_Name>
   TABLESPACE  <Tablespace_name>
   BUILD [ IMMEDIATE | DEFERRED ]
   REFRESH [ FAST | COMPLETE | FORCE ] ON [ DEMAND | COMMIT ]
   START WITH <First_Refresh_Time>  NEXT <Refresh_Time>
   WITH [ ROWID | PRIMARY KEY ]
   [ ENABLE | DISABLE ] QUERY REWRITE
   AS
   <Select_Statements>
 
 
BUILD 절  (처음 MView를 어떻게 생성할 것인가에 대한 문장)
 
  - IMMEDIATE : Default 값이다. 만드는 즉시 MV에 값이 생성이 된다.
 
  - DEFERRED  : 이 옵션을 이용해서 MView를 만들면 초기에는 값이 생성되어 있지 않는다.
                그리고, DBMS_MVIEW.REFRESH()를 이용해서 Refresh 될 때 비로서 값이 생성된다.
                단, 처음에는 반드시 Full Refresh를 수행해야지만 전체 값이 생성이 된다.
 
 
REFRESH(Refresh를 어떻게 할 것인가에 대한 문장)
 
  - FAST     : MV의 Master Table에 DML이 발생할 경우, 변경된 DML만 MV에 반영한다.
               이는 MV가 FAST일 때 System이 자동으로 "Direct Loader Log"라는 것을 생성하고,
               여기에 변화된 direct-path DML을 보관하고 있기 때문이다.  
 
  - COMPLETE : MV와 Master Table을 비교하면서 COMPLETE Refresh를 수행한다.
               그리고 비록 MV가 FAST일지라도, COMPLETE Refresh를 수행하면 COMPLETE로 수행된다.
 
  - FORCE    : Default 값이다.
               ????
  
 
ON(언제 Refresh를 할 것인지에 대한 문장)
 
  - DEMAND : Default 값이다.
             Refresh는 DBMS_MVIEW.REFRESH()를 이용해서 Refresh 될 때 변경된 DML이 반영된다.
 
  - COMMIT : DML이 발생한 후 Commit을 만나면 그 결과를 바로 MView에 반영한다.
          *** 자세한 사항은 아래의 "13. Materialized View의 On Commit Refresh 기능"을 참조
 
 
START WITH 절 : 처음 언제 Refresh를 할 것인지를 명시한다.
 
   NEXT 절  :  Refresh 주기를 몇시간으로 줄 것인지 명시한다.
 
 
WITH (Logging 정보를 명시하는 문장)
 
  - ROWID : Master Table의 Primary Key가 없을 경우 ROWID를 이용해서 생성할 수 있다.
            실제로 ROWID가 훨씬더 빠른 속도를 보장한다.
 
  - PRIMARY KEY : Default 값이다. Master Table의 Primary Key를 이용해서 MView를 생성한다.
 
  - WITH ROWID, PRIMARY KEY 이렇게 동시에 사용할 수도 있다.
 
 
 
10. Materialized View 의 Index
 
◎ Materialized View 는 Table에서 사용하는 Index를 다 사용할 수 있다.
 
   - Oracle 9i 이상의 Materialized View에서는 Function Based Index 뿐만 아니라,
 
   - Oracle 8i 이상에서는 Index Organize Table도 가능하다.
     자세한 것은 "12. Materialized View에서 Index Organize Table을 이용하기" 참조.
 
 
◎ 예제..
 
   SQL> desc FND_USER_MV
    Name                            Null?    Type
    ------------------------------- -------- ----
    USER_ID                         NOT NULL NUMBER(15)
    USER_NAME                       NOT NULL VARCHAR2(100)
    COUNT(*)                                 NUMBER
   
    SQL> create index FND_USER_MV_N1 on FND_USER_MV(USER_ID);
   
    Index created.
 
 
11. Materialized View를 만드는 방법 (사용예제)
 
◎ Materialized View를 만들때 고려사항
   a. 만들려고 하는 Materialized View가 어떤 Type 인지..
   b. Index는 어떻게 생성을 할 것인지.
   c. Refresh 주기를 어떻게 설정할 것인지...
   d. ON COMMIT을 사용할 지, 아니면 ON DEMAND를 사용할 지..
 
◎ 일반적으로 REFRESH FAST ON COMMIT 인 Materialized View는 실제 마스터 테이블의 DML 작업시
   기존 보다 많은 부하가 마스터 테이블에 생성이 됩니다.
 
다음과 같은 Privileges를 갖어야 한다.
   SQL> grant create any materialized view to disuser;
   SQL> grant drop any materialized view to disuser;
   SQL> grant alter any materialized view to disuser;
   SQL> grant global query rewrite to disuser;
   SQL> grant analyze any  to disuser;
 
◎ Materialized View를 만들기 위한 전제 조건.
  
   1) Materialized View의 대상이 되는 모든 Table은 Analyze 되어 있어야 합니다.
      SQL> analyze table GL.GL_PERIOD_STATUSES compute statistics;
      Table analyzed.
 
   2) 사용되는 모든 MASTER Table의 컬럼에 대해 LOG Table을 생성합니다.
      SQL> create materialized view log on applsys.fnd_user
         2 with rowid, sequence(user_id, user_name) including new values;
  
   3) On Commit Fast Refresh를 원한다면, Master Table이 존재하는 Schema에서 MView를 만들어야 함
  
     - 그렇지 않으면 다음의 에러가 발생
       *) "ORA-12015: cannot create a fast refresh materialized view from a complex query"
       *) "ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view"
  
     - 따라서 APPS와 같은 Schema에서 여러 User의 Table을 이용해서 Materialized View를 만든다면,
       "REFRESH COMPLETE ON DEMAND" or "REFRESH FORCE ON DEMAND" 로 만들 수 밖에 없다.
  
     - 그렇지 않고, 해당 Schema에 모든 Master Table에 존재하는 경우는 해당 Schema에
       Materialized View를 만들고 이에 대한 Synonym을 주는 것이 가장 좋다.
  
  
◎ Single Table에 대한 Materialized View 만들는 방법:
  
   1) Primary Key가 있는 Single Table에 대한 MV
  
     *) Primary Key가 있는 Single Table 경우는 하나의 Row를 결정할 수 있는
        Unique 한 값이 있기 때문에 어떤 방식으로든 쉽게 만들 수 있다.
  
     i) WITH PRIMARY KEY를 이용해서 Log Table을 만든 경우
  
        SQL> create materialized view log on applsys.wf_in
           2 with primary key, sequence(corrid) including new values;      
  
        SQL> create materialized view applsys.wf_in_mv refresh fast
           2 with primary key as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view applsys.wf_in_mv;
  
        SQL> create materialized view applsys.wf_in_mv build immediate refresh fast on commit
           2 with primary key as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view wf_in_mv;
  
       SQL> create materialized view applsys.wf_in_mv build immediate refresh fast on commit
           2 with  primary key as select  msgid, sum(corrid) from wf_in
           3 where corrid <> '10' group by msgid;
  
  
     ii) WITH ROWID를 이용해서 Log Table을 만든 경우
  
        SQL> create materialized view log on wf_in
           2 with rowid, sequence(msgid, corrid) including new values;      
  
        SQL> create materialized view wf_in_mv refresh fast
           2 with rowid as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view wf_in_mv;
  
       SQL> create materialized view wf_in_mv build immediate refresh fast on commit
           2 with rowid as select msgid, corrid from wf_in;  
  
        SQL> drop materialized view wf_in_mv;
  
       SQL> create materialized view wf_in_mv build immediate refresh fast on commit
           2 with rowid as select  msgid, sum(corrid) from wf_in
           3 where corrid <> '10' group by msgid;
  
  
   2) Primary Key가 없는 Single Table에 대한 MV
  
      *) Primary Key가 없는 Single Table 경우는 하나의 Row를 결정할 수 있는
         Unique 한 값이 없기 때문에 Unique하게 만드는 방법을 써야만 한다.
  
      *) 만약 Unique하게 하는 방법을 적용하지 않고 만든다면 다음의 에러가 난다.
 
         SQL> create materialized view log on fnd_user
            2 with rowid, sequence(user_id, user_name) including new values;

         SQL> create materialized view fnd_user_mv refresh fast
            2 as select user_id, user_name from fnd_user;
         ERROR at line 1:
         ORA-12014: table 'FND_USER' does not contain a primary key constraint
 
         SQL> create materialized view fnd_user_mv refresh fast with rowid as
            2 select distinct user_id, user_name from fnd_user;
         ERROR at line 2:
         ORA-12015: cannot create a fast refresh materialized view from a complex query
       
         SQL> create materialized view log on fnd_user with rowid including new values;

         SQL> create materialized view fnd_user_mv refresh fast with rowid
            2 as select user_id, user_name, count(*) from fnd_user group by user_id, user_name;
         ERROR at line 2:
         ORA-12033: cannot use filter columns from materialized view log on "APPLSYS"."FND_USER"
  
 
      *) 위의 에러를 해결하기 위해서는 하나의 Row를 Unique하게 만든는 방법을 적용해야 한다.
  
        SQL> create materialized view log on fnd_user
           2 with rowid, sequence(user_id, user_name) including new values;
 
        SQL> create materialized view fnd_user_mv build immediate refresh fast with rowid
           2 as select user_id, user_name, count(*) from fnd_user group by user_id, user_name;
 
        SQL> drop materialized view fnd_user_mv;
 
        SQL> create materialized view fnd_user_mv build immediate refresh fast on commit with rowid
           2 as select user_id, user_name, count(*) from fnd_user group by user_id, user_name;
  

      *) 또한 Aggregation이 있는 경우 반드시 Count(*)를 써서 Unique 성을 보장해야 한다.
  
        SQL> create materialized view log on mv1
           2 with rowid, sequence(key, bonus) including new values;
  
        SQL> create materialized view mv1 build immediate refresh fast on commit
           2 s
           3 elect count(*), substr(key,1,1),
           4       sum(decode(trim(key),'aa',bonus,0)) as s1,
           5       count(decode(trim(key),'aa',bonus,0)) as c1,
           6       sum(decode(trim(key),'ab',bonus,0)) as s2,
           7       count(decode(trim(key),'ab',bonus,0))as c2,
           8       sum(decode(trim(key),'ac',bonus,0)) as s3,
           9       count(decode(trim(key),'ac',bonus,0)) as c3
          10 from mv1
          11 group by substr(key,1,1);
  
◎ Multiple Joined Table에 대한 Materialized View 만들는 방법:
 
  ※ Multiple Joined Table에 대한 Materialized View를 만들기 위해서는
     반드시 해당 Table과 Column에 대한 Log Table을 만들어야 한다.
 
  ※ 그리고 두개의 Table이 Join이 되어서 결과가 나오는 구조이기 때문에,
     각 Row에 대한 Unique 성을 보장하기 위해서 반드시 Count(*)를 사용 해야 합니다.
 
  ※ Materialized View를 만들 경우는 반드시 해당 User에서 만들는게 좋다.
 
  ※ 다음과 같은 SQL에 대해 Materialized View를 만드는 것을 가정하자.
      create materialized view xen_emp_sal_mv
      refresh fast on commit
      as
      select count(*) as cnt
            ,xef.employee_id
            ,xef.name
            ,xef.registration_number
            ,xsf.year
            ,xsf.month
            ,sum(xsf.salary) as salary
            ,count(xsf.salary) as cnt_salary
            ,sum(xsf.bonus) as bonus
            ,count(xsf.bonus) as cnt_bonus
            ,sum(xsf.education) as education
            ,count(xsf.education) as cnt_education
            ,sum(xsf.benefit) as benefit
            ,count(xsf.benefit) as cnt_benefit
        from xen_employee_f xef
            ,xen_salary_f   xsf
       where xef.employee_id = xsf.employee_id
       group by xef.employee_id, xef.name, xef.registration_number, xsf.year, xsf.month;
 
  ※ 이때 전제 사항은 xen_employee_f, xen_salary_f Table은 DISUSER Schema에 존재하고,
     Materialized View 또한 DISUSER Schema에 만들면서, Fast Refresh, On Commit의
     Materialized View를 만듬을 전제로 한다.
 
  ※ 그렇지 않고 APPS Schema에 만들고자 한다면, LOG는 DISUSER Schema에 생성하고,
     APPS Schema에서 Materialized View는 REFRESH COMPLETE ON DEMAND로 만들어야 한다.
 
  ※ 그러면 다음과 같은 방법으로 만들 수 있다.
     SQL> create materialized view log on disuser.xen_employee_f
        2 with rowid, sequence(employee_id, name, registration_number)
        3 including new values;
     
     SQL> create materialized view log on disuser.xen_salary_f
        2 with rowid,
        3 sequence(salary_id, employee_id, year, month, salary, bonus, education, benefit)
        4 including new values;
     
     SQL> create materialized view xen_emp_sal_mv
       2  tablespace euld
       3  pctfree 10
       4  build immediate
       5  refresh fast on commit
       6  enable query rewrite
       7  as
       8  select count(*) as cnt
       9        ,xef.employee_id
      10        ,xef.name
      11        ,xef.registration_number
      12        ,xsf.year
      13        ,xsf.month
      14        ,sum(xsf.salary) as salary
      15        ,count(xsf.salary) as cnt_salary
      16        ,sum(xsf.bonus) as bonus
      17        ,count(xsf.bonus) as cnt_bonus
      18        ,sum(xsf.education) as education
      19        ,count(xsf.education) as cnt_education
      20        ,sum(xsf.benefit) as benefit
      21        ,count(xsf.benefit) as cnt_benefit
      22    from xen_employee_f xef
      23        ,xen_salary_f   xsf
      24   where xef.employee_id = xsf.employee_id
      25   group by xef.employee_id, xef.name, xef.registration_number, xsf.year, xsf.month;
 
 
 
12. Materialized View에서 Index Organize Table을 이용하기 (8.1.6 이상)
 
◎ Oracle 8.1.6 이전 버젼에서 Materialized View의 Index 사용...
  - Oracle 8i 이전에는 CREATE MATERIALIZED VIEW 는 'ORGANIZATION INDEX'를 가질수 없었다.
  - 즉 MV 는 heap-organized table 만 사용가능하였다.
  - 이전 version 에서 IOT 를 이용한 MV 를 생성시는 ora-905를 발생시킨다
 
◎ 하지만 Oracle 8.1.6 부터는 Heap 또는 Index-Organized Table(IOT)을 위한 logging이 가능하다

◎ 사용 예제
 
   ※ 다음과 같은 Mview가 있다고 가정하자
      SQL> -- Create heap-organized table, test.t1
      SQL> create table t1 (col1 number primary key, col2 varchar2(255));
 
      SQL> -- Create Index-Organized Table (IOT), test.t1_iot
      SQL> create table t1_iot (col1 number, col2 varchar2(255),
         2 constraint t1_iot_pk primary key (col1))
         3 organization index tablespace userdata
         4 including col1 overflow tablespace userdata;
 
 
   ※ 두 가지 형태의 Index Organize Table을 만들어 보자.
      SQL> -- Demonstrate IOT MV w/OVERFLOW on heap master, test.t1
      SQL> create materialized view mv_t1 organization index 
        2  as select * from t1;
 
      SQL> -- Demonstrate IOT MV w/OVERFLOW on IOT master, test.t1_iot
      SQL> create materialized view mv_t1_iot
        2  organization index 
        3  including col1 overflow tablespace userdata 
        4  refresh with primary key 
        5  as select * from t1_iot;
 
 
   ※ 데이터 딕셔너리에 대한 분석
      SQL> -- Tables:
      SQL>
-- T1 := heap table (iot_type is null)< /FONT>
      SQL>
-- T1_IOT := iot (iot_type = 'IOT')
      SQL> -- SYS_IOT_OVER_24894 := overflow segment for T1_IOT (object_id 24894)
 
      SQL> -- Materialized Views:
      SQL>
-- MV_T1 := MV for master T1 (no associated OVERFLOW - see above CREATE)< /FONT>
      SQL>
-- MV_T1_IOT := MV for master T1_IOT
      SQL> -- SYS_IOT_OVER_24900 := overflow segment for MV_T1_IOT (object_id 24900)
 
      SQL> select table_name, iot_name, iot_type from dba_tables 
        2  where owner = 'TEST'
        3  and (table_name like '%T1%' or iot_name like '%T1%') 
        4  order by table_name;
 
      TABLE_NAME                     IOT_NAME                 IOT_TYPE
      ------------------------------ ---------------------- ------------
      MV_T1                                                    IOT
      MV_T1_IOT                                                IOT
      SYS_IOT_OVER_24894             T1_IOT                    IOT_OVERFLOW
      SYS_IOT_OVER_24900             MV_T1_IOT                 IOT_OVERFLOW
      T1
      T1_IOT                                                   IOT
 
      6 rows selected.
 
      SQL> -- MV Summary
     
SQL> select table_name, master, can_use_log, refresh_method 
        2  from dba_snapshots 
        3  where master in ('T1_IOT','T1');
 
      TABLE_NAME                     MASTER               CAN REFRESH_MET
      ------------------------------ -------------------- --- -----------
      MV_T1                          T1                    YES PRIMARY KEY
      MV_T1_IOT                      T1_IOT                YES PRIMARY KEY
 
      2 rows selected.
 
 
 
13. Materialized View의 On Commit Refresh 기능 (8.1.6 이상)
 
◎ Oracle 7이나 8 버젼의 snapshot은 지정된 시간에 refresh 작업이 기동되는 반면,
   Oracle 8i 버젼의 새로운 기능인 ON COMMIT refresh는 트랜잭션 COMMIT과 동시에
   원격 MATERIALIZED VIEW(구 SNAPSHOT)에 대하여 refresh 작업이 기동된다.
 
◎ Materialized View Log 작성 예제
  - ON COMMIT refresh 기능을 위해서는 반드시 INCLUDING NEW VALUES 옵션을 사용 하여야 한다.
   SQL> drop materialized view log on emp;
   SQL> create materialized view log on emp
      2 with rowid (empno, ename, job, mgr, hiredate, sal, deptno)
      3 including new values;
   SQL> select * from emp;

◎ ON COMMIT Materialized View 작성 예제
   SQL> drop materialized view mv_emp;
   SQL> create materialized view mv_emp
      2 build immediate
      3 refresh fast on commit
      4 as
      5 select count(*), deptno, sum(sal), count(sal)
      6   from emp
      7  group by deptno;
 
  ※ ON COMMIT refresh 기능을 위해서는 반드시
     ***  BUILD IMMEDIATE(default)
     ***  ON COMMIT 옵션
    
을 사용하여야 한다.
 
   SQL> select * from mv_emp;
          COUNT(*)     DEPTNO   SUM(SAL) COUNT(SAL)
        ---------- ---------- ---------- ----------
                 3         10       8750          3
                 5         20      10875          5

   SQL> select deptno from emp where empno = 7934;
            DEPTNO
        ----------
                10
   SQL> update emp set deptno = 20 where empno = 7934;
   SQL> commit;
   SQL> select * from mv_emp;
          COUNT(*)     DEPTNO   SUM(SAL) COUNT(SAL)
        ---------- ---------- ---------- ----------
                 2         10       7450          2
                 6         20      12175          6
  

◎ ON COMMIT refresh 사용에는 다음과 같은 제약 조건이 있다:
  
   1. Materialized View는 반드시 COUNT, SUM 등과 같은 aggregate 함수를 갖거나,
      죠인으로만 구성되어야 한다.
  
   2. 하나의 테이블을 대상으로 반드시 COUNT(*) 함수가 기술되어야 한다.
  
   3. GROUP BY 절에 의해서 grouping 대상