ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [python] sqlalchemy > sessionmaker > autocommit, autoflush에 대해
    공부 이야기 2024. 2. 26. 09:23

    단 두 줄로 데이터베이스와 커넥션(세션)을 맺을 수 있는 sqlalchemy 코드를 보고 문득 떠올랐다.

    sessionmaker() 메소드를 구성하기 위해 어떤 항목들이 숨겨져있을까.

    그 중에서 이번에 확인할 내용은 autocommit, autoflush이다.

     

     

    (1/4) Autoflush = True, Autocommit = True

    -> begin(), commit() 메소드를 직접 호출해줘야 INSERT 쿼리문(트랜잭션)이 BEGIN ~ COMMIT 으로 감싸져서 처리됨을 확인할 수 있음

     

    -> begin() 메소드를 호출하지 않고 commit() 메소드를 호출한 경우, No Transaction is begun 에러 발생

     

    -> flush() 메소드를 호출해주면 begin(), commit() 메소드를 호출하지 않아도 자동으로 COMMIT이 발생

     

     

    (2/4) Autoflush = False, Autocommit = True

    -> begin() 메소드를 호출하지 않으면 No transation is begun 에러가 발생

     

    session 객체 값이 변경이 되어도 UPDATE 쿼리가 발생하지 않고 DB 변경도 없음

     

    -> flush()를 호출해준 경우 자동으로 COMMIT 및 DB update 처리

     

     

    (3/4) Autoflush = True, Autocommit = False

    -> begin() 메소드를 호출하지 않아도 No transaction is begun 에러가 발생하지 않고 INSERT 쿼리가 실행 + 특이한 점은 자동으로 SELECT 조회 쿼리를 실행하는데 마지막에는 ROLLBACK이 발생

    자동으로 SELECT 조회 쿼리를 실행하는 이유는 return todo

    -> UPDATE 쿼리도 위와 동일하게 처리

     

    -> flush() 메소드를 호출해도 COMMIT이 발생하지 않음 ROLLBACK 확인

     

    INSERT 쿼리도 마찬가지로 DB로 쿼리는 실행이 되지만 ROLLBACK

     

    -> commt() 메소드를 호출해야 정상적으로 DB INSERT 처리 완료(COMMIT)

     

    -> flush() 메소드를 호출하지 않고 commit() 메소드를 호출해도 위와 동일하게 동작함(COMMIT)

     

    -> UPDATE 쿼리도 동일

     

     

    (4/4) Autoflush = False , Autocommit = False

    -> flush() 메소드만 호출한 경우 DB ROLLBACK

     

    -> commit() 메소드까지 호출해야 DB INSERT가 정상적으로 실행(COMMIT 됐다는 뜻ㅎ)

     

    -> flush() 메소드를 호출하지 않고 commit() 메소드만 호출했을 때 DB COMMIT이 발생하는 것으로 보아, "commit이 발생하면 flush가 자동으로 발생하는 사실을 알 수 있음"

     

    -> begin() ~ commit() 메소드 안에 INSERT 쿼리와 SELECT 쿼리를 추가하면 하나의 트랜잭션 단위로 처리함

    SELECT 쿼리를 호출하는 메소드를 INSERT 쿼리를 호출하는 메소드 뒤에 추가했음에도 불구하고 SELECT 쿼리가 먼저 호출되는걸 확인할 수 있음

    -> todos 테이블의 PK는 id임, WHERE 절에 NULL이 들어가 있음

    Mysql DB에서 Auto Increment 방식으로 값을 할당받는 PK인 경우, 입력값으로 PK를 넘기지 않을 경우 NULL을 조회함

    물론 PK에는 NULL이 들어갈 수 없기 때문에 값이 조회되는 경우는 없음

    하지만 개발 의도가 INSERT 했던 row를 조회하기 위함이라면 위와 같은 방식을 사용하면 안됨

    이 경우 refresh() 메소드를 사용해야 함 (근데 sqlalchemy에서 자동으로 조회함)

     

    -> 한편, UPDATE 쿼리의 경우 begin() 메소드를 호출하면 already begun 에러가 발생함

     

    -> UPDATE 쿼리의 경우 begin() ~ commit() 메소드 안에 SELECT 쿼리와 함께 추가할 수 없음. 따라서 호출 순서대로 쿼리 실행

     

    번외)

    테스트를 수행하면서 auto increment 칼럼인 id가 중간에 건너뛰어진걸 볼 수 있다.

    이는 flush()만 호출하고 commit()을 호출하지 않았을 때 ROLLBACK된 상황에서 발생한 것으로

    ROLLBACK이 발생한 경우에도 id 값은 재사용하지 않는 MySQL 특성이다.

Designed by Tistory.