I am using sqlalchemy 0.8.5 with mysql 5.5 and think an intermittent failure I am seeing may be due to an issue in sqlalchemy. Very infrequently I receive an error from Session.add() stating the instance "is already attached to session 'XXX' (this is 'YYY')" (see below for stack trace). I understand the typical reason this error is raised, but I do not believe the instance should still be attached to XXX, even though it was shortly before (milliseconds) since Session.close() was called on the session. A second session is created, and in the vast majority of cases the objects from the first session can be added to the second session without error, but occasionally (<1% of the time) add() raises InvalidRequestError.
My understanding of Session.close() is that upon return all instances should be detached from the session and their instance state session_id attribute should no longer reference the session. This does not appear to be happening since adding the instance to a different session fails since the instance is still attached to the previous session. In reading the code it appears as though it is expected in certain situations for the session_id to continue to refer to the session after close since the check for already attached checks session_id as well as whether the session remains in the sessions registry. I have created a patch to check not only the instance state reference to the session but also check whether the session still contains the instance before raising the InvalidRequestError, but I do not have a way to reproduce this issue outside our production system, and am very leery of hacking sqlalchemy for a production system with my limited understanding of session internals. I would appreciate any comments on possible causes of the symptoms I am seeing as well as comments on the wisdom of applying this patch and running it in a production system. I am in the process of upgrading to sqlalchemy 0.9.7 but that is at least a month away and hope to make traction on this issue before then. I also do not believe upgrading will help since there are no sqlalchemy bugs on this. TIA for any advice or suggestions you have. diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index dcb68d6..b06e624 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1749,10 +1749,13 @@ class Session(_SessionClassMethods): if state.session_id and \ state.session_id is not self.hash_key and \ state.session_id in _sessions: - raise sa_exc.InvalidRequestError( - "Object '%s' is already attached to session '%s' " - "(this is '%s')" % (orm_util.state_str(state), - state.session_id, self.hash_key)) + other_session = _sessions.get(state.session_id, None) + if other_session and (other_session.identity_map.contains_state(state) or + state in other_session._new): + raise sa_exc.InvalidRequestError( + "Object '%s' is already attached to session '%s' " + "(this is '%s')" % (orm_util.state_str(state), + state.session_id, self.hash_key)) if state.session_id != self.hash_key: if include_before and Stack trace: File "<snip>", line 81, in quota_allocation_management yield File "<snip>", line 235, in __init__ tx.add(self.configuration) File "<snip>", line 35, in __call return attr(*args, **kwargs) File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1399, in add self._save_or_update_state(state) File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1418, in _save_or_update_state self._save_or_update_impl(st_) File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1667, in _save_or_update_impl self._update_impl(state) File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1661, in _update_impl self._attach(state) File "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.8.5-py2.6-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1755, in _attach state.session_id, self.hash_key)) -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.