关于python:SQLAlchemy:flush()和commit()之间有什么区别?

SQLAlchemy: What's the difference between flush() and commit()?

在SQL炼金术中,flush()commit()有什么区别?

我读过这些文件,但没人比我更聪明——他们似乎假定我没有事先的理解。

我对它们对内存使用的影响特别感兴趣。我正在从一系列文件(总共大约500万行)将一些数据加载到数据库中,我的会话偶尔会失败——这是一个大型数据库和一台内存不足的机器。

我想知道我是否使用了太多的commit()而没有足够的flush()调用——但如果不真正理解其中的区别,就很难判断!


会话对象基本上是正在进行的数据库更改事务(更新、插入、删除)。这些操作在提交之前不会持久化到数据库中(如果您的程序在会话中间事务中由于某种原因中止,则会丢失其中任何未提交的更改)。

会话对象用session.add()注册事务操作,但在调用session.flush()之前,它们还没有与数据库通信。

session.flush()向数据库传递一系列操作(插入、更新、删除)。数据库将它们维护为事务中的挂起操作。在数据库收到当前事务的提交(这是session.commit()所做的)之前,这些更改不会永久保存到磁盘,也不会对其他事务可见。

session.commit()提交(持久)对数据库的更改。

调用flush()总是作为调用commit()的一部分。

当使用会话对象查询数据库时,查询将返回来自数据库和它所持有的未提交事务的刷新部分的结果。默认情况下,会话对象autoflush其操作,但可以禁用。

希望这个例子能更清楚地说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#---
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() sends your SQL statements to the database

commit() commits the transaction.

当session.autocommit==false时:

如果autoflush==true,commit()将调用flush()。

当session.autocommit==true时:

如果您还没有启动事务(可能还没有启动事务,因为您可能只使用此模式来避免手动管理事务),则不能调用commit()。

在此模式下,必须调用flush()以保存ORM更改。刷新还有效地提交了您的数据。