행위

트랜잭션 개요

DB CAFE

thumb_up 추천메뉴 바로가기


1 트랜잭션(Transaction)[편집]

1.1 트랜잭션이란?[편집]

  1. 동시에 실행되는 작업의 단위를 의미
  2. 사용자의 의도에 따라 여러 개의 문장으로 구성된 트랜잭션은 반드시 동시에 실행(COMMIT)되거나 취소(ROLLBACK), ALL OR NOTHING
  3. RDBMS는 트랜잭션을 통해 작업의 단위를 결정함으로써 작업 결과의 신뢰성을 확보
notifications_active 트랜잭션의 예시 - 금융 거래 계좌 이체 - A계좌에서 100만원을 B계좌로 이체한다면 최소 2가지 작업이 수행
1) A계좌에서 100만원 출금
2) B계좌에 100만원이 입금
  • A계좌에서 100만원 출금은 성공했지만 B계좌에 100만원이 입금되기 전에 시스템이 다운된다면 B계좌에는 100만원이 입금되지 않고, A의 계좌에서만 100만원이 없어지게 된다.
  • 이를 방지하기 위해 이 2개의 과정을 하나의 트랜잭션으로 묶어서 2개의 과정이 모두 처리되지 않으면 ROLLBACK 하여 거래가 취소되도록 함, 거래의 신뢰성을 확보

4. 트랜잭션의 시작과 종료

 1) 시작
   이전 트랜잭션이 종료된 이후
   DML(INSERT, UPDATE, DELETE) 문장이나 DDL(CREATE, ALTER, DROP, TRUNCATE), DCL(GRANT, REVOKE)문장이 실행되었을 때 시작
 2) 종료
   2-1) COMMIT 이나 ROLLBACK 명령이 실행시 종료
   2-2) DDL이나 DCL문장이 실행이 완료되면 자동으로 종료
   2-3) 사용자의 정상 종료 시 종료
   2-4) 데드락(DeadLock)이 걸리면 트랜잭션의 일부만 종료
  • 트랜잭션은 하나의 세션에서 하나만 시작할 수 있다.
  • DML 인 경우 반드시 COMMIT 이나 ROLLBACK 으로 종료한다.
  • DDL, DCL 은 오라클 자동 제어


5. 트랜잭션 과 언두 세그먼트(Undo segment)

  • DML 작업을 ROLLBACK 하기 위해서는 작업 이전 데이터를 Undo Tablespace 저장함.
  • Undo Tablespace 자동으로 관리되며 사용자는 구조정보를 직접 볼 수 없으며 트랜잭션에서만 사용 됨.
  • 오라클은 작업이 발생하면 즉시 테이블의 내용을 변경 -> DELETE나 UPDATE문을 실행하면 테이블의 정보 또한 즉시 변경


6. 트랜잭션 과정

  • DML 문장은 과정이 모두 동일
notifications_active 예시) A테이블의 B컬럼의 row 데이터값 5를 7로 update 하는 과정
1) UPDATE 명령
2) 문장 수행을 위해 오라클은 Undo Segment 를 결정
3) 테이블에 저장되어있던 원래 값(5)이 Undo Segment에 저장됨
4) UPDATE 된 값(7)이 테이블에 저장됨
5) 값이 변경된 행(레코드)는 독점 잠금(Lock)이 발생
6) 테이블에는 공유 잠금(Lock)이 발생
7) 트랜잭션이 COMMIT되면 잠금은 해제, 변경된 값(7)은 영구히 저장
8) 트랜잭션이 ROLLBACK 되면 Undo Segment 에 저장했던 원래 값(5)을 테이블로 환원하고 잠금이 해제

7. 독점 잠금(Exclusive Lock)과 공유 잠금(Shared Lock)

 1) 독점 잠금 : 현재 세션 이외에는 접근을 불허 하는 잠금
 - 트랜잭션으로 행에 잠금이 발생하면 다른 세션에서는 해당 행을 검색할 수 없고 Undo Segment의 정보만 확인 가능
 - 이때 테이블에는 공유 잠금이 발생
 2) 공유 잠금 : DML 작업으로 행이 잠겨있는 테이블에 대해서 DDL (DROP, ALTER)작업을 방지

1.2 실습[편집]

1.2.1 트랜잭션 잠금의 이해[편집]

 1) 실습에는 2개의 일반 사용자 세션이 사용된다.
 2) 동일한 계정으로 접속한 SQL Developer를 2개 실행한다.
 3) 2개의 창은 [세션1]과 [세션2]로 구분한다.



 filter_1 * 실행 순서 : [세션1] 순서1) >> [세션1] 순서2) >> [세션2] 순서3) >> [세션1] 순서4) >> [세션2] 순서5)

  • [세션1]

 arrow_downward 순서1)

SELECT * FROM student WHERE sname='TEST';

UPDATE student SET avr = 0.1
 WHERE sname='TEST';

 arrow_downward 순서2)

-- COMMIT 을 하지 않았으므로 TEST의 행에는 독점 잠금이 발생하고, student 테이블에는 공유 잠금이 발생.
-- student 테이블의 avr 값은 새로 변경되었고 Undo Segment 에는 TEST의 이전 avr 값이 저장되었다.

SELECT sno, sname, avr
  FROM student
 WHERE sname='TEST';

 arrow_downward 순서4)

-- 트랜잭션 완료
COMMIT;



  • [세션 2]

 arrow_downward 순서3)

-- 다른 세션에서 동일한 행을 조회.독점 잠금이 세션1에 의해 락이 걸려있으므로 Undo Segment 에서 값을 읽어온다.
SELECT sno, sname, avr
  FROM student
 WHERE sname='TEST';

 arrow_downward 순서5)

-- 세션1에서 커밋 후 다시 조회 
SELECT sno, sname, avr
  FROM student
 WHERE sname='TEST';

1.2.2 트랜잭션에 의한 대기[편집]

1) 실습에는 2개의 일반 사용자 세션이 사용된다.
2) 동일한 계정으로 접속한 SQL Developer를 2개 실행한다.
3) 2개의 창은 [세션1]과 [세션2]로 구분한다.

 filter_1 * 실행 순서 : [세션1] 순서1) >> [세션2] 순서2) >> [세션2] 순서3) >> [세션1] 순서4) >> [세션1] 순서5) >> [세션2] 순서6) >> [세션2] 순서7) >> [세션1] 순서8)

  • [세션 1]

 arrow_downward 순서1)

-- 데이터 변경(UPDATE) 하면 트랜잭션 시작 되고 TEST의 행에는 독점 잠금이 발생된다.
--  student 테이블에는 공유 잠금이 발생되고 student 테이블은 새로운 학과인 '사회'로 변경.
--  Undo Segment 에는 TEST 의 변경 이전 학과인 '화학' 정보가 저장된다.

SELECT sno, sname, major
FROM student
WHERE sname='TEST';

UPDATE student SET major='사회'
WHERE sname='TEST';

SELECT sno, sname, major
FROM student
WHERE sname='TEST';

 arrow_downward 순서4)

-- 상대방이 독점잠금이 걸린 행을 다시 변경하려고 시도하였으나
-- 세션1의 트랜잭션이 끝나지 않아 무한 대기상태에 임.
--   트랜잭션을 완료한다
COMMIT;

--커밋을 완료하면 상대 세션인 세션2는 대기상태에서 빠져나와 새로 변경된 데이터가 적용된다.

 arrow_downward 순서5)

-- 세션1의 트랜잭션은 마무리되었고 세션2의 트랜잭션은 진행중인 상태
-- 현재 검색을 하면 내가 적용한 상태로 검색된다
SELECT sno, sname, major
  FROM student
 WHERE sname='TEST';

 arrow_downward 순서8)

-- 세션2의 트랜잭션이 완료되고 검색을 한다   
SELECT sno, sname, major
  FROM student
 WHERE sname='TEST';

  • [세션 2]

 arrow_downward 순서2)

-- 다른 세션에서 변경하고 트랜잭션이 완료되지 않은 행을 검색한다
-- Undo Segment 의 데이터를 읽어온다
SELECT sno, sname, major
  FROM student
 WHERE sname='TEST';

 arrow_downward 순서3)

-- 독점 잠금이 걸린 행을 UPDATE 시도한다
UPDATE student SET major='경제'
 WHERE sname='TEST';

 arrow_downward 순서6)

-- 무한 대기가 풀리고 명령이 실행된 후 검색
SELECT sno, sname, major
FROM student
WHERE sname='TEST';

 arrow_downward 순서7)

-- 트랜잭션 완료
COMMIT;