[프로시저 내용]

A테이블에(departments_dev) 접근하여 조회된 값을 커서에 담아서 B테이블(departments_dev2)에 입력하는 프로시저


0. 테스트용 생성 DDL (테스트용이라 간단하게 생성함)

-- departments_dev 생성 (데이터 조회용 테이블)

CREATE TABLE `departments_dev` (

`dept_no` CHAR(4) NOT NULL,

`dept_name` VARCHAR(40) NOT NULL

)

COLLATE='utf8_general_ci'

ENGINE=InnoDB;


insert into departments_dev values('d009','Customer Service');

insert into departments_dev values('d007','Sales');  -- 중복데이터 만큼 입력되는지 확인하기 위해 3번 insert 함

insert into departments_dev values('d007','Sales');

insert into departments_dev values('d007','Sales');


-- departments_dev2 생성 (데이터 입력용 테이블)

CREATE TABLE `departments_dev2` (

`dept_no` CHAR(4) NOT NULL,

`dept_name` VARCHAR(40) NOT NULL

)

COLLATE='utf8_general_ci'

ENGINE=InnoDB;



1. 프로시저 생성 

DELIMITER //

-- drop procedure if exists SP_cursor_dev;

create procedure SP_cursor_dev(IN v1 char(4), IN v2 varchar(40))   -- INPUT 값을 받는 프로시저 생성 


BEGIN 

DECLARE c1 varchar(4);

DECLARE c2 varchar(40);

DECLARE c_Done int default 0;


/* 여기에 커서를 정의 합니다. */

DECLARE mCursor CURSOR FOR

select dept_no,dept_name

from departments_dev

where dept_no=v1

and dept_name=v2;


/* 데이터가 없으면 c_Done에 1 */

DECLARE CONTINUE HANDLER FOR NOT FOUND SET c_Done=-1;

OPEN mCursor;


/* 반복합니다. */ 

REPEAT

 /* 반환된 필드값을 변수에 담습니다. */

FETCH NEXT FROM mCursor INTO c1,c2;


IF NOT c_Done then

/* 수행할 쿼리리 여기에 작성합니다. */   

insert into departments_dev2 values(c1,c2);


END IF;


/* c_Done이 1이 될때까지 반복 합니다. */

UNTIL c_Done END REPEAT;


CLOSE mCursor;


select concat('error : ', c_Done);  -- 에러코드 출력


END //

DELIMITER ;


2. 프로시저 정상실행

 CALL SP_cursor_dev('d007','Sales');


2. 프로시저 에러실행 (존재하지 않는 값)

 CALL SP_cursor_dev('d077','Salaa');  


3. 프로시저 결과 확인 

select * from departments_dev2;




참고

[SP] Cursor 사용 예제 : http://dbguide.tistory.com/entry/SP-Cursor-%EC%82%AC%EC%9A%A9-%EC%98%88%EC%A0%9C




오라클 교육과정을 통해 DB를 처음 시작하다 보니, 트랜잭션이나 Lock 관리 중요성에 대해서는 전혀 인지하지 못하고 있었다.

교육과정에서 언급도 되지 않고 지나갔던 것으로 기억한다. 동시성 제어와 관련하여 Undo에 대해서만 열심히 공부했던 기억이 난다. 

트랜잭션과  Lock 관련하여 너무 간과하고 있었던 것 같아서 공부를 위해 내용을 정리해 본다.

 

[참고 도서 : 오라클 성능고도화 원리와 해법 I]

 

#ANSI/ISO SQL standard에서 정의하고 있는 4가지 트랜잭션 고립화 수준

 

1) 0 레벨 (리드 언커밋티드(Read Uncommitted))

-  Dirty Read, Non-Repeatable Read, Phantom Read 발생

- Oracle 지원하지 않음

 

2) 1 레벨 (리드 커밋티드(Read Committed))

- Dirty Read  qkdwl

- 대부분의 DBMS가 기본모드로 채택하고 있는 일관성 모드

- DB2, SQL Server, Sybase의 경우 읽기 공유 Lock을 이용하여 구현. 하나의 레코드를 읽을 때 Lock을 설정하고 해당 레코드를 빠져 나가는 순간 Lock 해재

-Oracle은 Lock을 사용하지 않고 Undo 데이터를 제공하는 방식으로 구현

 

3) 2 레벨 (리피터블 리드(Repeatable Read))

- 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때 까지 후행 트랜잭션이 갱신하거나 삭제하는 것을 불허함으로써 같은 데이터를 두번 쿼리했을 때 일관성있는 쿼리를 리턴

-팬텀 리드(Phantom Read) 현상은 여전히 발생

-DB2, SQL Server의 경우 트랜잭션 고립화 수준을 Repeatable Read로 변경하면 읽은 데이터에 걸린 공유 Lock을 커밋할 때 까지 유지하는 방식으로 구현.

-Oracle은 이 레벨을 명시적으로 지원하지 않지만 for update절을 이용하여 구현 가능.

 

4) 3 레벨 (시리얼라이저블 리드(Serializable))

-선행 트랜잭션이 읽은 데이터를 후행 트랜잭션이 갱신하거나 삭제하지 못할 뿐만 아니라 중간에 새로운 레코드를 삽입하는 것도 막아줌.

-완벽한 읽기 일관성 모드를 제공.

 

* 오라클은 트랜잭션 고립화 수준을 높이더라도 Lock을 사용하지 않으므로 동시성이 저하되지 않는다.

  Undo 데이터를 활용함으로써 높은 수준의 동시성과 읽기 일관성을 유지하는 대신 다른 DBMS에 없는 Snapshot too old가 발생한다.

 

'Database(DB)' 카테고리의 다른 글

[DBeaver] 무료 DB툴 디비버 단축키 - 쿼리 줄바꿈  (1) 2024.12.03

+ Recent posts