python - SQLAlchemy : flush ()와 commit ()의 차이점은 무엇입니까?


SQLAlchemy에서 flush()commit() 사이의 차이점은 무엇입니까?

필자는 문서를 읽었지만 더 현명한 사람은 아닙니다. 그들은 내가 가지고 있지 않은 사전 이해를하는 것처럼 보입니다.

나는 특히 메모리 사용에 대한 그들의 영향에 관심이있다. 일련의 파일 (총 약 500 만 행)에서 일부 데이터를 데이터베이스로로드하고 있으며 세션이 가끔 떨어지는 경우가 있습니다. 메모리가 크지 않은 대용량 데이터베이스와 시스템입니다.

너무 많은 commit() flush() 호출과 충분하지 않은 flush() 호출을 사용하고 있는지 궁금합니다. 그러나 차이점을 실제로 이해하지 않고도 말할 수 없습니다!




Answers


Session 객체는 기본적으로 데이터베이스 변경 (업데이트, 삽입, 삭제)의 진행중인 트랜잭션입니다. 이러한 작업은 커밋 될 때까지 데이터베이스에 유지되지 않습니다 (중간 세션 트랜잭션에서 어떤 이유로 프로그램이 중단되고 커밋되지 않은 변경 내용이 손실되는 경우).

세션 객체는 트랜잭션 작업을 session.add() 와 함께 등록하지만 session.flush() 가 호출 될 때까지 데이터베이스와 통신하지 않습니다.

session.flush() 는 일련의 작업을 데이터베이스에 전달합니다 (삽입, 업데이트, 삭제). 데이터베이스는이를 트랜잭션에서 보류중인 조작으로 유지합니다. 변경 사항은 디스크에 영구적으로 유지되거나 데이터베이스가 현재 트랜잭션 (즉, session.commit() 대한 COMMIT를 수신 할 때까지 다른 트랜잭션에서 볼 수 없습니다.

session.commit() 은 데이터베이스에 대한 변경 사항을 커밋 (지속)합니다.

flush()항상 commit() ( 1 ) 호출의 일부로 호출됩니다.

세션 개체를 사용하여 데이터베이스를 쿼리하면 쿼리는 데이터베이스와 보유한 커밋되지 않은 트랜잭션의 플러시 된 부분 모두에서 결과를 반환합니다. 기본적으로 Session 객체는 autoflush 으로 조작을 수행하지만 비활성화 될 수 있습니다.

바라건대이 예제는이 명확하게 :

#---
s = Session()

s.add(Foo('A')) # The Foo('A') object has been added to the session.
                # It has not been committed to the database yet,
                #   but is returned as part of a query.
print 1, s.query(Foo).all()
s.commit()

#---
s2 = Session()
s2.autoflush = False

s2.add(Foo('B'))
print 2, s2.query(Foo).all() # The Foo('B') object is *not* returned
                             #   as part of this query because it hasn't
                             #   been flushed yet.
s2.flush()                   # Now, Foo('B') is in the same state as
                             #   Foo('A') was above.
print 3, s2.query(Foo).all() 
s2.rollback()                # Foo('B') has not been committed, and rolling
                             #   back the session's transaction removes it
                             #   from the session.
print 4, s2.query(Foo).all()

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



@snapshoe가 말했듯

flush() 는 SQL 문을 데이터베이스로 보낸다.

commit() 은 트랜잭션을 커밋합니다.

session.autocommit == False 일 경우 :

autoflush == True이면 commit ()은 flush ()를 호출합니다.

session.autocommit == True 일 때 :

트랜잭션을 시작하지 않은 경우에는 commit ()을 호출 할 수 없습니다. 트랜잭션을 수동으로 관리하지 않으려면이 모드 만 사용하기 때문에 트랜잭션을 시작하지 않았을 수는 없습니다.

이 모드에서는 flush ()를 호출하여 ORM 변경 사항을 저장해야합니다. 플러시는 효과적으로 데이터를 커밋합니다.