2021.12.16 TIL

서승원·2021년 12월 16일
0

TIL

목록 보기
37/68

Transaction
트랜잭션이라고 하며, 여러개의 논리를 묶어 하나의 논리로 만들어 하나라도 오동작할 때 일괄적으로 취소할 수 있게 해준다. 업무논리의 핵심으로 이용된다.
ex) 판매가 이루어지면 매상은 증가하고 재고는 감소한다.
계좌이체가 이루어지면 보내는사람의 잔고는 감소하고 받는사람의 잔고는 증가한다.

우선 2개의 PUTTY창을 이용해서 확인해본다. 1번 PUTTY 창에서 AUTOCOMMIT 이라는 값을 확인해보고 FALSE로 바꿔준다. 그리고 1번 PUTTY에서 temp14_T Table에 3개의 레코드를 INSERT 했다. COMMIT이란 MSSQL의 구조를 예로 들면 위와 같은 DB의 구조에서 A,B 각각 두 콘솔 창이 있다면, 두 콘솔은 LOG라는 공간을 거쳐서 별도의 프로세스가 돼서 별도의 소켓을 통해 개별적인 Connection으로 DB에 접속한다. LOG라는 공간은 테이블에 접하기 전 임시적인 저장공간으로 볼 수 있다.먼저 A 프로세스로부터 X라는 수정사항이 입력되면 LOG에 먼저 X가 입력이 된다. 이 때, AUTOCOMMIT 값이 TRUE라면 입력 즉시 COMMIT 돼어 LOG에 입력된 X 값이 테이블 temp14_T에 입력되게 된다. 하지만 AUTOCOMMIT값이 FALSE라면 COMMIT 되지않고 LOG에 X 라는 값이 남아있을 것이다. COMMIT이란 LOG라는 임시적인 공간에 남아있는 데이터를 DB의 TABLE에 입력하는 것이다. A의 LOG에 남아있는 데이터는 B의 Connection을 통해서는 접근할 수가 없다. B의 LOG는 A의 LOG, 즉 커넥션이 별도이기 때문에 B의 LOG를 통해 Table을 탐색한다. 또한 이때 , A의 LOG에 다시 입력된 Z라는 값이 있다면 데이터는 COMMIT 되는 선택지만이 아닌 ROLLBACK 이라는 선택지도 있다. ROLLBACK 된 데이터는 LOG에서 사라지지만 TABLE에 입력되지도 않는다. 입력됐던 사실이 없게 되는 것과 마찬가지다.
다시 위의 코드로 돌아가면, A의 LOG에 INSERT 된 3개의 RECORD가 남아있는 것이고 역시 2번 PUTTY에서 temp14_T를 SELECT 하면 아무 레코드도 없다고 출력된다.
그리고 1번 putty에서 COMMIT 해주게 되면 1,2번 PUTTY 모두에서 3개의 레코드가 insert된 것을 확인할 수 있게 된다.

이번엔 1번 PUTTY에서 입력돼있던 레코드에 수정을 가한 상황이다. COMMIT도 ROLLBACK도 시키지않고 UPDATE의 동작이 LOG에 남아있다.

이 상황에서 2번 PUTTY에서 no가 5인 레코드를 DELETE하려 하면 아무 동작도 하지않고 대기하게 된다. 이유는 1번 PUTTY의 LOG에서 UPDATE 된 대상에 대해서는 일종의 LOCK이 걸린 상태가 되기 때문이다.
1번 PUTTY에서 다시 ROLLBACK 이라는 결정을 내려주면 1,2번 PUTTY 모두에서 no가 5인 recrod가 DELETE 된다.
트랜잭션의 핵심은 ALL OR NOTHING이다. 묶여있는 코드 중 하나라도 에러가 발생하거나 동작하지 않으면 다른 코드들도 동작하지 않아야 한다.이를 보장하기 위해 JDBC, PROCEDURE를 사용한 두 방법을 확인해본다.

JDBC

mysql에서 입력한 그대로를 jdbc에서의 표현으로 옮겨주면 된다. SET AUTOCOMMIT = FALSE;는 conn.setAutoCommit( false );로 옮겨준다. AUTOCOMMIT이 활성화되면 트랜잭션에서의 로직에 의해 한 코드가 잘못됐을 때 나머지 코드들을 ROLLBACK 시킬 수 없기 때문에 반드시 필요하다.
SQL문으로 작성된 게시글에 대해 추천 수를 늘리는 코드와 추천 관계 ( 추천 대상이 되는 글 번호, 추천한 사람의 ID ) 의 테이블을 추가하는 코드를 작성한다. 그리고 두 SQL문을 Statement에 담아 execute시켜준다. execute 과정에서 error가 발생하지 않는다면 try문 맨 아래의 conn.commit();으로 DB에서 두 코드가 commit 될 것이다. 하지만 에러가 발생하면 catch 문의 내용이 실행된다. conn.rollback() 을 통해서 이미 적용된 코드가 ROLLBACK 돼서 트랜잭션의 로직이 적용된다.

위 코드를 같은 입력값으로 2번 실행하면 2번에 대해 apple이 2번 추천을 하는 것은 Recom_HT의 PK가 no+uid로 CONSTRAINT로 정해져있어 , no duplicate의 원칙이 깨지기때문에 ROLLBACK된다.

PROCEDURE

프로시져를 이용한 방법이다. EXIT 라는 HANDLER를 DECLARE 한다. 이는 JDBC에서의 TRY,CATCH 문과 같은 작용을 한다. SQLEXCEPTION에 대해서 에러가 발생하면 BEGIN 이하의 내용을 실행하게 된다.
역시, 에러가 발생하면 ROLLBACK 돼서 트랜잭션의 원칙을 보장해준다.
proc_tx3()을 2번 CALL해서 동작시키면 역시, 8번에 대해 recom 값이 1에서 증가하지않고, ROLLBACK이 제대로 된 것을 확인할 수 있다.

profile
2년차 백엔드 개발자, crimy

0개의 댓글