728x90

이번달 퀴즈는 두가지 부정형 조인 NOT IN, NOT EXISTS 의 차이점을 설명하는것입니다.

문제를 명확히 하기 위해서 아래와 같은 상황을 고려하겠습니다.

테이블 : TEST1

     NO

Name

1

Lee

2

Kim

Park

<NULL>

Jang

<NULL>

<NULL>

 

테이블 : TEST2

NO 

 

Name

 

1

Lee

2

Kim

Park

<NULL>

Jang

* <NULL>은 데이터가 NULL값인 경우입니다.

 

테스트 쿼리

1) NOT IN 의 경우

SELECT *
   FROM TEST1 A
  WHERE A.NO NOT IN (SELECT NO FROM TEST2)

2) NOT EXISTS 의 경우

SELECT *
   FROM TEST1 A
  WHERE NOT EXISTS (SELECT 1 FROM TEST2 B WHERE A.NO = B.NO)

위와 같은 상황에서 두 개의 테스트 쿼리를 실행하여 그 결과에 대해 왜 그렇게 나왔는지 설명하세요.

 

 

답안)

이번달 퀴즈의 문제는 NOT IN과 NOT EXISTS의 차이점이 무엇인가입니다.

 

1번, 2번의 경우에서 NO의 값 1,2,3은 모두 결과에 나오지 않습니다. 즉, TEST2에 속하지 않는것을 찾는것이므로 결과에 나오지 않게됩니다. 차이점은 NULL 값이 결과에 나오는가 아닌가에 있습니다.

 

NOT IN(1번)의 경우

where절의 조건이 맞는지 틀리는지를 찾는것입니다. 그런데 NULL은 조인에 참여하지 않기때문에 결과에서 빠집니다. 여기서 TEST1의 NULL값이 나오지 않은 이유는 IN 서브쿼리의 결과에 NULL유무에 영향을 받지 않습니다. 즉, TEST2의 NO컬럼에 NULL값이 없어도 TEST1의 NO컬럼의 NULL값은 결과에 나오지 않습니다.

 

NOT EXISTS(2번)의 경우

EXISTS는 서브쿼리가 TRUE인지 FALSE인지 체크하는 것이므로  NOT EXISTS는 서브쿼리가 FALSE이면 전체적으로 TRUE가 됩니다. 서브쿼리에서 TEST1과 TEST2의 조인시 NULL은 결과에서 빠지게 됩니다. 이것은 서브쿼리를 FALSE로 만들게 되고 전체적으로 TRUE가 되어 TEST1의 NULL값이 결과에 나오게 됩니다.

 

이번 퀴즈는 매우 쉬운것 같으나 자칫 잘못 생각할 수 있는 내용이기 때문에 퀴즈로 다루었습니다. 일반적으로 대용량을 처리할 때 성능상의 이유로 Hash Anti-Join, Merge Anti-Join으로 유도하기 위해 NOT EXISTS를 NOT IN으로 바꿔서 처리하기도 합니다. 이때 두 부정형 조인의 결과가 같다는 전제 조건이 있어야 합니다. 그러나 위에서와 같이 연결고리가 되는 컬럼의 값 중 NULL이 포함된 경우 결과가 다르다는것을 주의해야 합니다.

 

 

=========================================================================================================================
=========================================================================================================================

 

 

not in 과 not exists 차이점 / 부정형을 긍정으로 변경할때

 

 

일반적으로 대용량을 처리할때 성능상의 이유로 Not Exists로 되어 있는 것을


Not In으로 바꿔서 Hash나 Merge Anti Join으로 유도하는 경우가 있는데


이는 Not Exists와 Not In의 관계가 "="이 성립한다는 전제 조건에서 이루어 진다.

 

하지만 모든경우 Not Exists와 Not In의 관계가 "=" 성립하는지에 대한 의문에서


아래와 같이 테스트를 해보았습니다.

 

<결론>
   Not In 과 Not Exists는 다르다.
    + Not IN과 Not Exists의 차이점은 연결고리가 되는 컬럼의 
      값중 null값을 처리하는 부분에서 차이가 난다.


<이유>
    + Not In 은 where 절의 조건이 만족하더라도 
      연결고리 컬럼이 Null값을 가진 다면 결과에서 무조건 제외 된다.


    + Not Exists는 Not In과 달리 Null값을 가진 row들도 결과에 포함된다.

 

    + 간단히 생각해보면 in은 조건에 만족하는 row를 찾는 것이고
      exists는 exists이하 절이 true인지 아닌지를 체크하는 것이기 때문에
      연결고리 컬럼의 값이 null값을 가질때 null은 조인에 참여하지 못하기 때문에
      in은 조건에 만족하는 것을 찾을 수 없는 것이고
      exists는 false의 값을 return한다.
      
      따라서 연결고리 값이 null값을 가질때
      Not in은 조인 연산을 하지 않기 때문에 결과에서 제외되며
      Not Exists는 exists이하의 절이 false를 리턴하고 거기에 대한 Not이기 때문에
      결과적으로 true가 되어 결과에 포함된다.

 

<참고사항>


  1) 부정형을 긍정으로 변경할 때


    + Not In일 때는 상관 없지만 Not Exists일때는 
      논리적으로 부정형을 긍정으로 변경 한 후 연결고리가 되는 컬럼이 null값 가질 경우에 
      대해서 반드시 True가 되도록 처리해 줘야 된다.
    + 즉 null 값을 가지는 컬럼에 대해서도 결과에 포함 되도록 해야 된다.

 

  ex)
      SELECT :current_il,
             A.SNG_NO,
             A.SNG_SEQ,
             A.JI_HANDO,
             A.JI_HAN_BAL,
       FROM IRMS_SNG_MAS A
      WHERE A.WONJ_ST2 = '1'
        AND A.GAGIGONG_GB IN('2','3')
        AND NOT EXISTS(SELECT 'X'
                         FROM IRMS_SNG_MAS G
                        WHERE G.WONJ_ST2 = '1'
                          AND G.GAGIGONG_GB IN('2','3')
                          AND (G.MANGI_IL < :current_il AND NVL(G.SIL_BAL,0) = 0)
                          AND G.SNG_NO = A.SNG_NO
                          AND G.SNG_SEQ = A.SNG_SEQ)

 

   <부정형을 긍정형으로 변경>


     + MANGI_IL이 NULL값을 가질때 반드시 참이 되도록 해야 됨.
     
      SELECT :current_il,
             A.SNG_NO,
             A.SNG_SEQ,
             A.JI_HANDO,
             A.JI_HAN_BAL,
        FROM IRMS_SNG_MAS A
       WHERE A.WONJ_ST2 = '1'
         AND A.GAGIGONG_GB IN('2','3')
         AND NOT (NVL(A.MANGI_IL,'99991231') < :CURRENT_IL AND NVL(A.SIL_BAL,0) = 0)

 

<테스트 테이브>
TEST_AJ01
TEST_AJ02

 

<데이타>

TEST_AJ01
========================
NO        MARRY_DT
-------------------
1        20030405
2        20030405
3        20030405
<null>   <null>
<null>   20030408


TEST_AJ02
========================
NO        MARRY_DT
-------------------
1        20030405
2        20030405
3        20030405
<null>   20030408

# NULL값을 가진 컬럼의 값은 <null>이라고 표현하였음


<테스트 SQL문>
1)
    SELECT *
      FROM TEST_AJ01 A
     WHERE A.NO NOT IN (SELECT NO FROM TEST_AJ02)
   
   ==결과==  -- 0건
   No rows returned

2)
    SELECT *
      FROM TEST_AJ01 A
     WHERE NOT EXISTS (SELECT 'X' FROM TEST_AJ02 B WHERE A.NO = B.NO)

   ==결과==  -- 2건
   <null>    <null>
   <null>    20030408

 

 

==========================================================================================================================
==========================================================================================================================

TEST1 테이블의 데이터 중 TEST2에 속하지 않는 데이터만 가져오기 ( NOT IN, NOT EXISTS, JOIN, UNION 으로 해결 )

중복되지 않는 데이터만 가져와서 INSERT 하거나

중복되는 데이터만 가져와서 UPDATE 할 때 사용할 수도 있다.

 

CREATE TABLE TEST1 (
 IDX INTEGER, 
 NAME VARCHAR(100)
)

CREATE TABLE TEST2 (
 IDX INTEGER, 
 NAME VARCHAR(100)
)


INSERT INTO TEST1 VALUES (1, 'A')
INSERT INTO TEST1 VALUES (2, 'B')
INSERT INTO TEST1 VALUES (3, 'C')
INSERT INTO TEST1 VALUES (4, 'D')
INSERT INTO TEST1 VALUES (5, 'E')


INSERT INTO TEST2 VALUES (3, 'C')
INSERT INTO TEST2 VALUES (4, 'D')
INSERT INTO TEST2 VALUES (5, 'E')
INSERT INTO TEST2 VALUES (6, 'F')
INSERT INTO TEST2 VALUES (7, 'G')


SELECT * FROM TEST1
SELECT * FROM TEST2

 

-- NOT IN

SELECT *
  FROM TEST1
 WHERE IDX NOT IN (
SELECT IDX
  FROM TEST2 )

 

-- NOT EXISTS

SELECT *
  FROM TEST1 A
 WHERE NOT EXISTS (
SELECT *
  FROM TEST2 B
 WHERE A.IDX = B.IDX )

 

-- SYBASE JOIN
SELECT *
  FROM (
 SELECT A.*
   , B.IDX B_IDX
   FROM TEST1 A
      , TEST2 B
  WHERE A.IDX *= B.IDX
    ) A
   WHERE B_IDX IS NULL
 

-- ANSI JOIN

SELECT *
  FROM TEST1 A
  LEFT JOIN TEST2 B
    on A.IDX = B.IDX
 WHERE B.IDX IS NULL
 

-- UNION ALL
SELECT A.IDX, A.NAME
  FROM (
  SELECT NAME
    , COUNT(*) CNT
    , COUNT(CASE WHEN GBN = 'A' THEN 1 END) A_CNT
    , IDX
    FROM (
    SELECT 'A' AS GBN
      , A.*
      FROM TEST1 A
    UNION ALL
    SELECT 'B'
      , B.*
      FROM TEST2 B
     ) A
   GROUP BY IDX, NAME
  ) A
 WHERE A.CNT < 2
   AND A_CNT = 1

728x90
728x90


많은 데이터의 추가, 변경 또는 삭제가 발생하여 인덱스의 키 값 분포가 크게 변경된 경우에는 해당 인덱스의 통계 갱신 즉, UPDATE STATISTICS를 실행하여 데이터베이스 엔진이 적절한 인덱스를 선택하도록 관리하는 작업이 필요합니다.
데이터베이스의 모든 사용자 정의 및 내부 테이블에 대해 UPDATE STATISTICS를 실행하기 위해서는 sp_updatestats를 실행합니다. sp_updatestats는 진행률을 나타내는 메시지를 표시하며, 업데이트가 완료되면 모든 테이블에 대해 통계가 업데이트되었다고 보고합니다. sp_updatestats는 비활성화된 비클러스터형 인덱스에 대한 통계를 업데이트하지만, 비활성화된 클러스터형 인덱스가 있는 테이블은 무시합니다.
명시적 또는 암시적 트랜잭션에서는 UPDATE STATISTICS가 허용되지 않습니다.
통계를 마지막으로 업데이트한 시기는 STATS_DATE 함수를 사용하여 확인 가능합니다

 

통계 업데이트하기

-- HumanResources.Employee 테이블의 모든 인덱스에 대한 통계 업데이트

USE AdventureWorks;

UPDATE STATISTICS HumanResources.Employee;

GO

-- HumanResources.Employee 테이블의 PK_Employee_EmployeeID 인덱스에 대한 통계 업데이트

USE AdventureWorks;

UPDATE STATISTICS HumanResources.Employee PK_Employee_EmployeeID;

GO

-- AdventureWorks 데이터베이스내의 모든 내부 테이블의 통계 업데이터

USE AdventureWorks;

EXEC sp_updatestats

GO

 

www.sqlleader.com/mboard.asp?exec=view&strBoardID=SS2005Admin&intSeq=104

728x90
728x90

BEST안은 적게 불러와서 적게 계산하는 것입니다. 
그 이외에도 여러가지 사항들이 많으나 몇가지만 적습니다.

- 검색조건과 무관한 인덱스 순서에 따른 문제 -> 검색 조건 우선순위에 따른 인덱스 컬럼 순서 재조정해서 재생성
- 데이터 제한 조건은 인덱스를 사용하도록
- 데이터 불러오는 양을 적게
- 사용자 ORACLE FUNCTION은 자제 (각 ROW단위로 연산이 일어나므로 매우 많은 CPU부하를 줌)
- 무조건 FULLTABLESCAN(이하 FTS)이 나쁜것은 아님
- NOT IN보다는 IN사용
- NOT EXISTS 보다는 EXISTS사용
- UNION보다는 UNION ALL사용

기본적으로는 CPU부담과 DISK I/O 를 적게 사용하는것이지만 서버의 CPU는 여유롭지만 DISK I/O가 많다면 DISK I/O를 줄여주는 방법이 좋겠고요 반대인 경우는 CPU사용을 줄여주는(연산작업) 방법이 좋은 튜닝 방법일것입니다.

위 세가지를 비교해 달라는 질문으로 알고 설명드립니다. 막상 질문사항만 놓고보자면 테이블크기, 데이터분포, 인덱스 컬럼 구성여부에 따라 상당히 다를 것입니다.

질문의 의도가 정확하게 나와 있지는 않으나 FTS를 한다는 것은 비교값이 인덱스컬럼에 적절히 설정되지 않았을 것 같은데요. 검색시 WHERE절에 들어가는 항목이 인덱스의 몇번째 컬럼인지 또한 그 분포도는 어떤지에 따라 FTS이 빠를 수도 있습니다.

우선은 해당 검색조건이 많은 데이터가 걸러지는 것인지 확인하여 인덱스를 추가/교체 구성할 필요가 있고 아니라면검색하고자 하는 조건이 인덱스 컬럼에 적정하게 설정되어 있다는 전제하에,

1. NOT IN은 각각의 데이터 자체를 비교하므로 CPU를 상대적으로 많이 사용하게 되며, 
2. NOT EXISTS는 KEY값(인덱스컬럼)만을 비교하므로 NOT IN에 비해여 자원을 덜 사용하게 될 것입니다.
    (하지만 때에 따라서는 NOT IN이 떠 빨리 결과를 내 줄수도 있습니다.)
3. 이와 달리 MINUS는 내부적으로 메모리내 SORT작업을 추가적으로 거치게 되고 일반적으로 서버자원을 좀 더 사용하므로 보통의 경우 많이 사용하지 않습니다.

결론적으로 말씀드리면 일반적인 SQL PLAN결과에 의한 튜닝기대효과는 NOT EXISTS > NOT IN > MINUS라고 볼수 있습니다. 하지만 테이블이 작은 경우라면 MINUS가 오히려 제일 빠른 결과를 내 줄 수도 있습니다.

부가적으로, FUNCTION BASED INDEX는 데이터 변경이 자주/많이 일어나는 경우,평상시 부하를 증가 시키므로 오히려 역효과가 날 수 있습니다. (해당 테이블을 사용하는 다른 SQL에 영향을 줄 수도 있고요...)
또한 정확한 조건MATCH가 일어나는 경우에만 인덱스를 사용하므로 해당 조건 추가시 효과에 대해 검토를 하여야 합니다.

※ 어느정도 개선되어 있는 상황이라면  tkprof를 사용하여 CPU자원을 많이 사용하는 것인지, DISK I/O를 많이 사용하는 것인지 판단하여 시간이 많이 걸리는/부하가 많이 걸리는 부분에 대한 개선을 하는것을 권장합니다.

질문의 의도를 정확히 판단하지 못하여 엉뚱한 답변이 되었을 수 있습니다. 양해바랍니다.



3. 실제로 NOT IN, NOT EXISTS, MINUS 부분은 인덱스를 타지 못하고 FTS(Full Table Scan)을 사용합니다.

오라클 교육을 받다보면, 아래와 같은 경우는 인덱스를 사용할수 없다고 나옵니다.

ⓛ NOT 연산자 사용
② IS NULL, IS NOT NULL 사용
③ 옵티마이저의 취사 선택
④ 외부적인 변형(External Suppressing)
⑤ 내부적인 변형(Internal Suppressing)

간단하게 정리를 해보았습니다.  참고하시길.
1. 연산자를 변경하여 처리하는 방법이 있습니다.
==> 경우에 따라서는 연산자 변경이 안될수도 있습니다. 특히 not 조건이라면 인덱스로 포함하려는 범위가 넓을것입니다. 

2. FTS와 인덱스 스캔 및 CBO vs RBO
 1) FTS로 수행한다고 무조건 느린것은 아닙니다.
  
  - 수행하실 테이블이 크지 않거나 칼럼 분포도가 좋지 않을경우는 오히려 FTS가 낫습니다. 
 2) Oracle 10g이상사용시 
   - 실제로 CBO를 사용하면, 비용개념으로 처리를 하기때문에 인덱스를 안타는 경우도 발생합니다. 
   - RBO를 사용하실 경우에는 실제로 계획된 대로 처리가 됩니다.
==> 10g 이상이라면,  Explain Plan을 해보시면 아실수 있을것입니다.
그리고,  테이블의 구조 및 상태에 따라 유동적이므로, 최적의 방법을 찾는것이 좋습니다. 

3. Not in 조건 사용시 
 1) 이 부분은 인덱스를 탈수 있는 연산자 변경을 하시면 가능합니다. 단 in 조건을 이용하셔서 그 값을 모두 뽑아도 된다면, 하나의 방법이 되겠지만, in에 조건값이 많아지면 그 성능은 그리 뛰어나다고 할수 없습니다.

종합적으로 보았을때, SQL 정보 및 시스템 상황을 고려해야할 경우라면 , 아래 두가지 정도입니다.
1) 성능상으로 크게 문제가 되지 않고, 해당 인덱스가 적용될 칼럼의 분포도 및 DML문(:insert ,update, delete)이 자주 발생하는 경우라면, CBO를 사용하여 비용단위로 추출된 쿼리로 FTS를 사용해도 괜찮을것입니다.(쿼리 실행 횟수도 체크가 필요할것입니다.)

2) 그러나, 해당 테이블이 대용량이고 select성으로 사용되는 테이블이고 ,해당 쿼리로 인하여 DB서버 및 AP에 부하가 우려되는 경우라면 말씀하신데로 연산자 변경이나 Function Based index를 사용하시는것이 좋을것입니다.

728x90
728x90

SELECT 문장에서 DISTINCT를 사용하는 이유는 중복된 행을 제거 하기 위해서 입니다. 이를 위해 오라클은 SORT를 수행 하며 당연히 소트를 위한 시간, 메모리 또는 디스크 공간이 필요 할 수도 있습니다. 그러니깐 가급적이면 사용 안 하는 것이 좋습니다. 추출되는 데이터가 순서에 의해 출력되지 않아도 된다면 아래의 경우처럼 EXISTS를 사용하는 것이 훨씬 효율적 입니다. 예제를 통해 이해 하도록 하겠습니다. 실제 비용(COST)의 경우도 1/10 정도로 줄게 됩니다.


SQL> set autotrace on
SQL> select distinct c.name
  2  from s_customer c, s_ord o
  3  where c.id = o.customer_id;

NAME
--------------------------------------------------
Beisbol Si!
Big John's Sports Emporium
Delhi Sports
Futbol Sonora
Hamada Sport
Kam's Sporting Goods
Kuhn's Sports
Muench Sports
OJ Atheletics
Ojibway Retail
Sportique

NAME
--------------------------------------------------
Unisports
Womansport

13 개의 행이 선택되었습니다.

경   과: 00:00:00.03

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (UNIQUE)
   2    1     NESTED LOOPS
   3    2       TABLE ACCESS (FULL) OF 'S_ORD'
   4    2       TABLE ACCESS (BY INDEX ROWID) OF 'S_CUSTOMER'
   5    4         INDEX (UNIQUE SCAN) OF 'S_CUSTOMER_ID_PK' (UNIQUE)

이 경우엔 S_ORD 테이블을 전체 스캔 한 데이터와 S_CUSTOMER 테이블의 데이터를 UNIQUE 인덱스를 이용하여 가져온 후 ROWIDD로 찾은 데이터와 비교하여 같은 아이디의 데이터가 있으면 추출하고 아니면 반복하는 구조를 가집니다. 그런 다음 c.name으로 SORT를 하게 되는 거죠…


Statistics
----------------------------------------------------------
         80  recursive calls
          0  db block gets
         57  consistent gets
          0  physical reads
          0  redo size
        651  bytes sent via SQL*Net to client
        503  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
         13  rows processed

이번엔 EXISTS를 이용하는 예 입니다.

SQL> select c.name
  2  from s_customer c
  3  where exists (select 1 from s_ord o
  4                where o.customer_id = c.id);

NAME
--------------------------------------------------
Unisports
OJ Atheletics
Delhi Sports
Womansport
Kam's Sporting Goods
Sportique
Muench Sports
Beisbol Si!
Futbol Sonora
Kuhn's Sports
Hamada Sport

NAME
--------------------------------------------------
Big John's Sports Emporium
Ojibway Retail

13 개의 행이 선택되었습니다.

경   과: 00:00:00.03

Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   FILTER
   2    1     TABLE ACCESS (FULL) OF 'S_CUSTOMER'
   3    1     TABLE ACCESS (FULL) OF 'S_ORD'

이 경우엔 S_CUSTOMER를 전체 스캔하고 S_ORD도 전체 스캔하여 필터링(ID가 같은 데이터가 있는지) 하므로 SORT를 이용하지는 않습니다. 그러므로 앞의 쿼리와 추출되는 데이터의 개수는 같지만 순서는 달리 나오는 겁니다.


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         49  consistent gets
          0  physical reads
          0  redo size
        651  bytes sent via SQL*Net to client
        503  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         13  rows processed



출처 : http://blog.daum.net/sadest/15853269

728x90
728x90

start /b 실행파일명

728x90
728x90

1. choice 명령 사용


e.g. CHOICE /T 10 /D y


2. Resource kit 설치하여 sleep 명령어 사용

728x90
728x90

Mysql에서 한글 정렬이 문제가 되는 것은 charset 때문이다.
이럴땐 my.cnf파일에 한줄을 추가 하는것으로 한글 정렬 문제를 해결 할 수 있다.

default-character-set=euc_kr

그리고 /etc/rc.d/init.d/mysqld restart 하여 Mysql데몬을 재시작하면 된다.

만약 Mysql 데몬을 재시작할 상황이 안된다면
쿼리문을 수정하는 방법이 있다.

binary(FIELD_NAME)


member 테이블에 있는 name이라는 이름 필드에 다음과 같은 값들이 있을때
'김철수','이영희','한국인'

SELECT name FROM member ORDER BY binary(name) DESC

위 쿼리를 실행하면 한국인,이영희,김철수 순으로 정렬이 된다.

728x90
728x90

2단계 커밋 (2-phase commit)이란?

2단계 커밋은 커밋(Commit)과 취소(Abort)를 수행하는데 두 단계를 거친다는 말이다.
첫 번째 phase는 준비단계로서, 데이터베이스는 커밋을 위한 모든 준비를 수행한다.
분산 트랜잭션에 참여한 모든 데이터베이스가 준비단계를 성공한 후에야 두 번째 phase인 커밋단계가 수행되는 것이다.
만약 분산 트랜잭션에 참여한 어느 한 데이터베이스라도 prepare를 실패한다면 두 번째 phase는 커밋이 아닌 취소를 수행한다.

여기서 분산 트랜잭션이란 네트워크에 분산되어 있는 자원들에 트랜잭션을 수행하는 것을 말한다.
예를 들어, 어떤 어플리케이션이 MS-SQL과 오라클에 데이터를 트랜잭션 하에서 수행해야 한다면 분산 트랜잭션이 필요하다. 대개의 경우 분산 트랜잭션은 턱시도, 티맥스, 엔트라와 같은 TP 모니터나 EJB, COM+ 등과 같은 컴포넌트 기반 미들웨어가 그 기능들을 제공한다.
분산 트랜잭션의 반대되는 개념으로서 로컬 트랜잭션은 단일 자원(데이터베이스)에 대한 커밋과 롤백을 수행하며 1-phase 커밋으로 트랜잭션을 수행한다.

 

많은 트랜잭션은 하나의 RM (보통 데이터베이스)만을 포함하고 있다. 이 경우 RM은 보통 트랜잭션을 확약하고 롤백하기 위한 대부분의 작업을 수행한다. (거의 모든 트랜잭션성 RM이 자체적인 트랜잭션 관리자를 내장하고 있는데, 이는 지역 트랜잭션, 즉 그 RM만이 참여한 트랜잭션을 처리할 수 있다.)

그러나 트랜잭션이 두 개, 혹은 그 이상의 RM (아마도 두 개의 개별적인 데이터베이스, 혹은 데이터베이스와 JMS 큐, 또는 두 개의 개별적인 JMS provider)을 포함하고 있다면 "모두 처리하든지 아니면 아무것도 처리하지 않는"다는 의미론이 그 RM 내에서 뿐 아니라 트랜잭션 내의 모든 RM에게 적용되도록 하고 싶을 것이다. 이런 경우 TPM은 2단계 확약을 전개할 것이다.

2단계 확약에서 TPM은 각 RM에게 "준비" 메시지를 보내어 그 RM이 준비가 되었고 트랜잭션을 수행할 수 있는지 물어본다. 모든 RM으로부터 긍정적인 답을 받으면 자신의 트랜잭션 로그에 트랜잭션이 확약되었다고 기록한 후 모든 RM에게 그 트랜잭션을 확약하라고 지시한다. 만일 어느 한 RM이라도 실패한다면, 재구동시 TMP에게 장애가 일어나는 시점에 미완으로 남아있던 트랜잭션의 상태에 대하여 질의하고, 그들을 확약하거나 혹은 롤백한다.

2단계 확약을 사회 생활에 비유해 보면 결혼식을 들 수 있다. 목사나 판사가 먼저 신랑, 신부에게 각각 "당신은 그/그녀를 당신의 남편/아내로 받아들이겠습니까?"하고 물어본다. 신랑, 신부 모두 "네"라고 대답하면 둘은 모두 결혼했음이 선언된다.; 그렇지 않다면 둘 모두 결혼하지 않은 상태로 남을 것이다. 누가 먼저 "네"라고 대답했는지에 상관없이, 한 사람은 결혼했는데 다른 쪽은 결혼하지 않은 상태로 남는 경우는 없다.



 


다음은 텀즈에 있는 2PC (2-phase commit)에 대한 정의 이다.

분산 컴퓨팅 환경에서 사용자의 트랜잭션을 처리하는데 있어, 트랜잭션 관리 프로그램은 트랜잭션에 관련된 모든 데이터베이스가 성공적으로 수정되었음을 확실하게 하기 위하여 2단계 커미트라고 불리는 프로토콜을 사용할 수 있다. 만일 데이터베이스의 수정이 성공적으로 이루어지지 않은 경우에, 그 트랜잭션은 롤백 상태가 되어 트랜잭션이 개시되기 이전의 상태로 되돌아간다. 만약 그 트랜잭션이 관련된 컴퓨터들에 의해 성공적으로 종료되었다면, 모든 데이터베이스의 수정을 위한 커미트가 이루어지며, 새로운 트랜잭션들이 자유로이 접근할 수 있도록 자원에 걸려 있던 로크들이 풀어진다.

아래에 이 프로토콜에 관한 간략한 설명이 있다.

  1. 한 컴퓨터 내에 있는 트랜잭션 관리 프로그램은 대체로 최초 요구에 연계되어, 관련된 모든 컴퓨터들을 대신하여 트랜잭션을 조정한다. 트랜잭션 관리 프로그램은 "트랜잭션 시작"이라는 내용을 로그 파일에 기재하고, 관련된 다른 컴퓨터들에게 트랜잭션 요청을 보낸다.

  2. 참여하고 있는 각 컴퓨터들은 자신의 로그에 트랜잭션을 기재하고, 다른 사용자가 쓸 수 없도록 데이터베이스 자원에 로크를 걸어 데이터베이스 변경을 수행하고, 트랜잭션 관리 프로그램에게 "커미트 할 준비가 되었다"는 메시지를 보낸다.

  3. 관리 프로그램은 관련된 모든 컴퓨터들로부터 "커미트 할 준비가 되었다"는 메시지를 받은 뒤에, 트랜잭션이 종료되었다는 사실을 로그 파일에 기재하고 나서, 모든 컴퓨터들에게 트랜잭션을 커미트 하라고 통보한다.

  4. 참여하고 있는 각 컴퓨터는 이 사실을 트랜잭션 로그 내에 기록한 다음, 자원에 걸려있던 로크를 풀어준다.

  5. 만약 모든 컴퓨터들이 트랜잭션을 커미트 하기 전의 어느 순간에 하나 이상의 컴퓨터에서 문제가 발생하면, 관리 프로그램은 트랜잭션이 시작되기 전의 상태로 되돌리도록 롤백 메시지를 전파한다.




응용 프로그래머에게 있어서의 2단계 커미트는 BEGIN, COMMIT, 그리고 필요한 경우 ROLLBACK 등의 프로그램 요청을 함으로써 구현된다. 

728x90

'용어' 카테고리의 다른 글

JEUS의 DB 연결  (0) 2010.07.28
ISV (independent software vendor)  (0) 2010.06.03
ERP (enterprise resource planning)  (0) 2010.01.21
클래스패스와 환경 변수, 그것이 알고 싶다.   (0) 2010.01.05
DBMS의 종류  (0) 2010.01.04
728x90

db2diag.log는 db에 문제가 생겼을 때 참조할 수 있는
가장 확실하고 가장 먼저 살펴볼 제 1의 레퍼런스이다.

db2diag.log는
active log, archive log, loadcopy, dump, tablespaces 와 함께
용량관리를 해주어야 하는 대상이 되는데

db2diag 커맨드는 db2diag.log를 분석하는 포매팅 툴로서,
제공하는 기능들 중에서 -A 옵션으로, db2diag.log를 분할하여 archive 할 수 있다.

in root's crontab

59 23 * * * su - ${instance user} -c "db2diag -A ${diagpath}/db2diag.log" > /dev/null 2>&1

매일 오후 23시 59분에 db2diag.log를 db2diag.log_YYYY-MM-DD-HH.MM.SS 형태로
하루에 하나씩 db2diag.log를 새로 생성하도록 해두면
로그를 검색하기도 쉽고 오래된 로그를 백업해두거나 삭제하는 정책을 만들기도 좋다.

728x90

'Db2 > Db2 reference' 카테고리의 다른 글

db2 접속환경설정  (0) 2011.03.13
db2 접속 및 종료  (0) 2011.03.13
DB2 데이터 암호화 함수 사용법  (0) 2011.03.08
Monitoring Script  (0) 2010.07.27
DB2 9의 메모리 모니터링과 튜닝  (0) 2010.07.13
728x90
ERP (enterprise resource planning) ; 전사적 자원 관리

ERP[이알피]란 제조업을 포함한 다양한 비즈니스 분야에서 생산, 구매, 재고, 주문, 공급자와의 거래, 고객서비스 제공 등, 주요 프로세스 관리를 돕는 여러 모듈로 구성된 통합 애플리케이션 소프트웨어 패키지를 뜻하는 산업 용어이며 재무 및 인적자원을 위한 모듈 또한 포함되어 있다.

일반적으로 ERP시스템은 관계형 데이터베이스를 기반으로 통합된 시스템의 형태이며, ERP시스템 구축은 비즈니스 프로세스 분석, 사용자 재훈련, 새로운 작업절차 등을 포함한다.

최근, ERP 아웃소싱을 제공하는 대표적인 ERP 패키지로는 SAP R/3, 오라클 Application, Peoplesoft, J. D. Edwards, BPCS 등이 있으며, 국내 패키지로는 삼성SDS의 Uni ERP, 영림원의 K시스템, 한국기업전산원의 탑 ERP 등이 있다.



ERP의 특징

1.

다국적, 다통화(多通貨), 다언어 지원
대부분의 ERP패키지는 다국적, 다통화, 다언어를 지원하고 있다. 여러 나라의 상거래 방식, 생산 방식을 패키지에서 지원하며 기업은 필요한 기능을 선택하여 사용할 수 있다.

2.

통합 시스템
ERP는 기업 활동 전 부분에 걸쳐있는 자원을 하나의 체계로 관리한다. 정보의 일관성, 실시간 처리로 인한 신속성 등은 기업의 경쟁력 제고에 중요한 기반을 제공한다.

3.

Best Practice에 의한 BPR 지원
ERP는 기업의 업무를 위한 기능을 "Best Practice"에 기반하여 제공한다. Best Practice는 세계의 일류 기업이 사용하는 업무 처리 프로세스를 공통화시킨 프로세스를 말하는데, 이를 자사에 도입함으로써 비즈니스 프로세스 리엔지니어링(BPR)을 실현하는 효과를 볼 수 있다.

4.

통합 데이터베이스
ERP의 업무 프로세스는 중앙의 데이터베이스를 매개로 기업활동 전반에 걸쳐 통합되어 있다. 통합 데이터베이스를 통해 하나의 정보는 한번만 입력되며 입력된 정보는 가공하지 않은 데이터로 어느 업무에서도 참조될 수 있다.

5.

매개변수 설정에 의한 단기간의 도입과 개발
ERP패키지는 매개변수 설정을 통해 필요한 기능을 구현하는 방식이다. 매개변수 설정을 이용하여 단기간에 시스템을 도입할 수 있다.

6.

개방형 시스템
대다수의 ERP시스템은 특정 하드웨어에 의존하지 않는 개방형 시스템이다. 다양한 하드웨어를 조합하여 클라이언트/서버 구조의 시스템을 구축할 수 있고 확장성도 뛰어나다.

728x90

'용어' 카테고리의 다른 글

ISV (independent software vendor)  (0) 2010.06.03
2단계 커밋  (0) 2010.03.02
클래스패스와 환경 변수, 그것이 알고 싶다.   (0) 2010.01.05
DBMS의 종류  (0) 2010.01.04
OLE DB에 대한 이야기  (0) 2009.12.17

+ Recent posts