Post

transaction(3)

들어가기에 앞서

제가 요즘 꽂힌 노래가 있습니다.. 제가 밴드 음악을 되게 좋아합니다. 국내 그룹도 좋아하긴 하는데, 밴드는 일본이 되게 잘 되어있어서 일본 밴드/락 음악을 자주 듣습니다.. 그 중 제가 좋아하는 aimer - daisy라는 노래가 있습니다.

https://www.youtube.com/watch?v=YoThSFe7Moo

노래 커버인데, 진짜 야무집니다. 함 들어보세요.
아무튼 각설하고, 저번 글에선 transaction(txn)의 ACID에 대해 알아보았습니다. 이번 글에선 txn을 postgresql에서 어떻게 실행하는지에 대해 알아보겠습니다.

postgresql

transaction을 시작하기 위해서, transaction을 시작한다고 명시적으로 표현하거나, 암묵적으로 표현하는 방법이 있습니다.

명시적 (explict) 표현

query를 작성할 때, 명시적으로 단어를 적어주는 방법입니다. 예시를 보도록 합시다.

1
2
3
4
5
6
BEGIN;
    query
    ....

COMMIT; --때에 따라서 rollback할 수도 있습니다. 
-- update한 결과를 원 상태로 돌리고 싶을 때 rollback 사용. 

transaction을 명시적으로 시작한다고 BEGIN이라고 표현해줍니다. 또한 query를 작성한 후, COMMIT/ROLLBACK을 통해 끝났다고 명시적으로 표현해줍니다. 제일 간단한 방법입니다. rollback에 대해 설명이 조금 부족한 듯 한데, begin을 할 때 당시 시점으로 돌아간다고 생각하면 됩니다.

암묵적 (implicity 표현)

제가 첫 글에서 “query에서 하나의 문장은 하나의 transaction이라고 생각할 수 있습니다.”
라고 했습니다. 이것이 암묵적인 transaction의 예시입니다. 링크 : https://amm0124.github.io/posts/txn1/

postgresql에선 begin 없이, autocommit모드로 transaction을 처리합니다.

autocommit

autocommit 모드가 무엇인지 궁금하셔야 합니다. autocommit 모드란 1개의 statement를 할 때마다 txn을 하는 것입니다. 예시로 간략한 sql insert statement를 보겠습니다.

1
2
insert ..1 
insert ..2

위 statement를 autocommit mode로 설정한다면

1
2
3
4
5
6
7
(begin) -- 암묵적으로 있다.
    insert ...1
(commit) -- 암묵적으로 있다.

(begin) -- 암묵적으로 있다.
    insert ...2
(commit) -- 암묵적으로 있다.

라고 표현 가능합니다.

이는 위험합니다. 왜냐하면 statement후 바로 commit을 하기에 속도도 느릴 뿐더러, 한 번의 실수라도 용납하지 않는다는 의미니까요.
autocommit을 끈다면 전체 query가 끝난 후, commit을 하는 방식입니다.

1
2
3
4
begin
    insert ..1 
    insert ..2
commit

형식이 되겠습니다.

savepoint

어렸을 때, 닌텐도로 포켓몬을 참 많이 했습니다. 제가 그 때, 포켓몬스터 dp를 플레이하면서 사천왕을 깼던 생각이 나네요.
아무튼 사천왕을 다 잡으면 포켓몬 마스터가 난천인데, 국룰 들어가기 전에 저장하시는거 다들 아시죠? ~~ 마지막 사천왕을 깬 후, 레포트를 작성해서 savepoint를 저장했던 기억이 납니다. 아무튼 저장하고 마지막 포켓몬 배틀을 할 때,에이스 포켓몬 한카리아스가 엄청 강력해서 첫 트에 못 깼던 경험이 납니다. 그리고 밀로틱도 엄청 강력했던 것으로 기억을 합니다. ~~ 제가 또 홍대병이 그때부터 있어서 전기타입을 안키웠던 기억이; ;

image

~~ 보통 레벨 50대 후반에 입성하는데 66은 너무합니다;; 드래곤다이브 한 방에 골로 갔던 제 포켓몬들이 기억나네요 팽도리를 시작으로 키웠으면 쉬웠을텐데 제가 풀타입을 그 땐 좋아했습니다 ㅋㅋ ~~

아무튼, transaction에도 savepoint가 존재합니다. 이는 명시적으로 지정을 해줘야 합니다. 왜 savepoint가 필요할까요?
바로 했던 작업을 반복하지 않음으로 성능 향상을 도모하기 위함입니다. 즉, 어떤 txn에서, savepoint를 지정해서, rollback시 begin 시점이 아닌, savepoint 시점으로 돌아가겠다는 의미를 명시적으로 표현하는 방법이 savepoint입니다. 예시를 들어봅시다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
BEGIN;
    select ..  -- (10,20,20)
    update ... -- (10,20,30)으로 update 됩니다.
    insert . ..
    select . ..  --(10,20,30)이라고 가정합시다.
    savepoint savepoint_1;
    delete ...
    select * ..
    update ... 
    select .. (10,20,40)이라고 가정합시다.
    rollback to savepoint_1;
    select ... (10,20,30)이 나옵니다. 왜냐하면 savepoint_1의 시점으로 돌아가기 때문입니다.
rollback; -- 이 내용은 저장되지 않습니다.

select . .. (10,20,20)

savepoint를 저장 후, rollback to savepoint 함으로, 내가 지정했던 savepoint로 돌아갈 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
BEGIN;
    INSERT INTO table1 VALUES (1);
    SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (2);
    SAVEPOINT my_savepoint;
    INSERT INTO table1 VALUES (3);

    -- rollback to the second savepoint
    ROLLBACK TO SAVEPOINT my_savepoint;
    SELECT * FROM table1;               -- shows rows 1 and 2

    -- release the second savepoint
    RELEASE SAVEPOINT my_savepoint;

    -- rollback to the first savepoint
    ROLLBACK TO SAVEPOINT my_savepoint;
    SELECT * FROM table1;               -- shows only row 1
COMMIT;

[출처 : https://www.postgresql.org/docs/current/sql-savepoint.html]
postgresql에서 발췌한 공식 문서입니다. release를 사용해서 savepoint를 바로 직전의 savepoint 상태로 돌리는 것을 알 수가 있습니다. 즉, savepoint를 삭제하는 것이 아닌, ctrl+z한다고 보시면 될 것 같습니다.

마무리하며

다음 글에선 isolation level에 대해 다뤄보도록 하겠습니다. 시험이 15시간밖에 안남았는데, 한가롭게 블로그 글이나 쓰고 있습니다. 근데 이렇게 정리하는 것이 또 재밌는지라… 아마 다음 글 까지 쓰고 공책 공부하러 가야할 것 같습니다 하핫..

This post is licensed under CC BY 4.0 by the author.