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')>]
이해가 너무 잘 되었습니다. 좋은 글 정말 감사합니다!