Re: [sqlalchemy] Session: close(), remove(), expire_all() and expunge_all()
Thank you very much for the answers. No doubts for now. 2011/3/18 Michael Bayer mike...@zzzcomputing.com On Mar 18, 2011, at 2:55 PM, Israel Ben Guilherme Fonseca wrote: Hi everybody, I'm new with SQLAlchemy and I'm trying to understand better the Session object. First of all, why the expire_all() exists? The purpose is to remove any database-loaded state from all current objects so that the next access of any attribute, or any query execution, will retrieve new state, freshening those objects which are still referenced outside of the session with the most recent available state. It is called automatically upon commit() or rollback() assuming an autocommit=False session, so that when the transaction, and its isolated environment, come to an end, subsequent accesses of those objects will acquire new data from whatever other transactions were committed subsequent to the previous transaction. expire_all() itself is useful when: - the session is used in autocommit=True mode, and new changes from other transactions are desired. - against a database that does not support transactions, or perhaps within a weakly isolated transaction, again to load changes from other transactions or connections. - when SQL statements have been executed against the current transaction using execute() which may have changed significant portions of loaded state on the database. Shouldn't it be always better to expunge_all() instead? If it is expired, at the use of the instance another query would be issued to reattach it anyway, so why keep useless instances in the identity map (maybe i'm wrong about this fact, i dont know exactly how the identity map works). They're not useless at all if you are performing operations upon them which span the scope of multiple transactions, or have any of the above use cases, and don't wish to re-establish a full graph of objects in memory. In-memory objects are essentially proxy objects to an underlying database transaction. The Session mediates this relationship. Second, when we should call the close() method? when you wish to release the transactional and connection pool resources of the Session and remove all objects. I dont think if i get it at all. Let's say that I have the following DAO: PersonDAO: def insert(self, person): session = Session() session.add(person) session.commit() // why the commit starts a new transaction? should'n it only start again the next database access? the commit ends the current transaction, and starts a new transaction from the Session's point of view. However, no SQL or transactional directives are emitted until the first SQL statement is emitted via the Session (either via execute(), query() iteration, or flush). So there is no new database transaction if you commit then cease to use that Session further. session.close() // is it necessary? Not strictly although it removes any state left over in the session, thereby establishing any remaining objects as detached. This is desirable since you might want to ensure that subsequent operations on those objects don't re-emit new SQL. Is the a Session instance directly associated to a Connection in the pool? Yes. This is documented here: http://www.sqlalchemy.org/docs/orm/session.html#what-does-the-session-do With the default pool size of 5, after 5 call of the insert method, the connection_overflow would be used? No. A single session uses one Connection per Engine at a time. By default, it keeps one connection open until rollback(), commit(), or close() is called. http://www.sqlalchemy.org/docs/orm/session.html#managing-transactionsillustrates this. What's the time to a Session expire? it expires things when commit or rollback is called.This is also in the above docs. And just to finish. Why do we use remove() for the scoped_session instead of the close()? scoped_session offers all of the methods of the underlying Session via a proxy pattern, so you can call close() on scoped_session, which calls close() on the actual session, or you can call remove(), which emits close() then removes the Session object itself from the registry. The latter has the advantage that any particular state established on the session, such as a Connection-based bind (see the example in http://www.sqlalchemy.org/docs/orm/session.html#joining-a-session-into-an-external-transaction), or other particular constructor options, are discarded. Shouldn't it be semantically identical only overrided for the contextual stuff? this would be scoped_session.close(). The distinction is discussed to some degree at http://www.sqlalchemy.org/docs/orm/session.html#lifespan-of-a-contextual-session. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com. To
Re: [sqlalchemy] Session: close(), remove(), expire_all() and expunge_all()
if it helps, I was just talking to my co-author (SQLA book) about how when I first wrote versions 0.1, 0.2, my concept of the Session was pretty much what you thought here. We hardy had expire at all, it seemed redundant versus expunge() to me (at that time called clear()). Only around 0.5 did I start getting my head around the expire with the transaction thing.There's a conceptual leap here about how to think about transactions (at least it was for me), and we really want to get this idea in the core of the book. On Mar 19, 2011, at 12:48 PM, Israel Ben Guilherme Fonseca wrote: Thank you very much for the answers. No doubts for now. 2011/3/18 Michael Bayer mike...@zzzcomputing.com On Mar 18, 2011, at 2:55 PM, Israel Ben Guilherme Fonseca wrote: Hi everybody, I'm new with SQLAlchemy and I'm trying to understand better the Session object. First of all, why the expire_all() exists? The purpose is to remove any database-loaded state from all current objects so that the next access of any attribute, or any query execution, will retrieve new state, freshening those objects which are still referenced outside of the session with the most recent available state. It is called automatically upon commit() or rollback() assuming an autocommit=False session, so that when the transaction, and its isolated environment, come to an end, subsequent accesses of those objects will acquire new data from whatever other transactions were committed subsequent to the previous transaction. expire_all() itself is useful when: - the session is used in autocommit=True mode, and new changes from other transactions are desired. - against a database that does not support transactions, or perhaps within a weakly isolated transaction, again to load changes from other transactions or connections. - when SQL statements have been executed against the current transaction using execute() which may have changed significant portions of loaded state on the database. Shouldn't it be always better to expunge_all() instead? If it is expired, at the use of the instance another query would be issued to reattach it anyway, so why keep useless instances in the identity map (maybe i'm wrong about this fact, i dont know exactly how the identity map works). They're not useless at all if you are performing operations upon them which span the scope of multiple transactions, or have any of the above use cases, and don't wish to re-establish a full graph of objects in memory. In-memory objects are essentially proxy objects to an underlying database transaction. The Session mediates this relationship. Second, when we should call the close() method? when you wish to release the transactional and connection pool resources of the Session and remove all objects. I dont think if i get it at all. Let's say that I have the following DAO: PersonDAO: def insert(self, person): session = Session() session.add(person) session.commit() // why the commit starts a new transaction? should'n it only start again the next database access? the commit ends the current transaction, and starts a new transaction from the Session's point of view. However, no SQL or transactional directives are emitted until the first SQL statement is emitted via the Session (either via execute(), query() iteration, or flush). So there is no new database transaction if you commit then cease to use that Session further. session.close() // is it necessary? Not strictly although it removes any state left over in the session, thereby establishing any remaining objects as detached. This is desirable since you might want to ensure that subsequent operations on those objects don't re-emit new SQL. Is the a Session instance directly associated to a Connection in the pool? Yes. This is documented here: http://www.sqlalchemy.org/docs/orm/session.html#what-does-the-session-do With the default pool size of 5, after 5 call of the insert method, the connection_overflow would be used? No. A single session uses one Connection per Engine at a time. By default, it keeps one connection open until rollback(), commit(), or close() is called. http://www.sqlalchemy.org/docs/orm/session.html#managing-transactions illustrates this. What's the time to a Session expire? it expires things when commit or rollback is called.This is also in the above docs. And just to finish. Why do we use remove() for the scoped_session instead of the close()? scoped_session offers all of the methods of the underlying Session via a proxy pattern, so you can call close() on scoped_session, which calls close() on the actual session, or you can call remove(), which emits close() then removes the Session object itself from the registry. The latter has the advantage that any