sqlalchemy flush commit rollback

x·2021년 4월 24일
1

sqlalchemy는 python의 ORM(object-relational mapper)이다. DB table의 row를 python object에 매핑해서 python 문법으로 조작할 수 있다. 그러나 조작만 하고 DB에 반영하지 않는다면 무의미한 짓을 한 것일 수 있다.

session은 in-memory에 존재하고 DB에 변경을 가하는 트랜잭션이라고 볼 수 있다.
lifecycle : 객체가 row로부터 인스턴스화되고 변경되고 DB에 commit되거나 rollback된다

이런 작업들은 commit되기 전까지 DB에 유지되지 않는다.

session 객체는 session.add()로 트랜잭션 작업을 등록하지만 session.flush()가 호출되기 전까지는 DB에 전달하지 않은 상태다.
session.flush()는 DB의 트랜잭션 buffer에 일련의 작업(insert, update, delete)을 전달한다. DB가 현재 트랜잭션에 대한 commit(session.commit())을 받을 때까지 다른 트랜잭션들에게 보여지거나 디스크에 영구 유지되지 않는다.

session.commit()은 DB에 변경을 영구적으로 반영한다

flush()는 항상 commit()이 호출될 때 같이 호출된다

rollback()은 DB 트랜잭션 buffer에 있는 것들을 버린다.

rollback()을 호출해도 이미 늦은 경우
1. autocommit=True인 상황에서 flush() 호출 한 경우
2. commit() 호출한 경우

# session 인스턴스 생성
s = Session()

# Foo('A') 인스턴스는 session에 추가됨
# DB에 commit 아직 안됨
s.add(Foo('A')) 

# session에 add만 했는데 query 날리면 값 출력됨
print(1, s.query(Foo).all())
s.commit()

s2 = Session()
s2.autoflush = False

s2.add(Foo('B'))

# flush()가 호출되지 않아 Foo('B') 인스턴스는 쿼리로 반환되지 않는다
print(2, s2.query(Foo).all())

# flush() 호출함으로써 Foo('B')는 Foo('A')와 같은 상태가 된다
s2.flush()                   

# Foo('B')는 아직 commit되지 않았다
print(3, s2.query(Foo).all())
# session으로부터 해당 session의 트랜잭션을 되돌린다
s2.rollback() 

# Foo('B')는 rollback되어 출력되지 않는다
print(4, s2.query(Foo).all())

Output:
1 [<Foo('A')>]
2 [<Foo('A')>]
3 [<Foo('A')>, <Foo('B')>]
4 [<Foo('A')>]

출처

1개의 댓글

comment-user-thumbnail
2021년 11월 25일

이해가 너무 잘 되었습니다. 좋은 글 정말 감사합니다!

답글 달기