Hello all, We are facing a problem when using history_meta.py recipe.
It seems like two concurrent transactions read the same (id,version) tuple at "#1" and then each one tries to insert a new row into the pbases_history table with the same pk (id, version) combination (see #2) By removing #2, the issue goes away but of course, there is no history kept anywhere. ####### CODE SNIPPET WHERE THE ISSUE IS TRIGGERED history_meta.py: attr['version'] = obj.version # 1 hist = history_cls() for key, value in attr.items(): setattr(hist, key, value) session.add(hist) # 2 obj.version += 1 ####### STACK TRACE: 140, in collection_post p2model.DBSession.flush() File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 150, in do return getattr(self.registry(), name)(*args, **kwargs) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1919, in flush self._flush(objects) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2037, in _flush transaction.rollback(_capture_exception=True) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__ compat.reraise(exc_type, exc_value, exc_tb) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2001, in _flush flush_context.execute() File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 367, in execute n.execute_aggregate(self, set_) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 459, in execute_aggregate self.execute(uow) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/unitofwork.py", line 526, in execute uow File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 65, in save_obj mapper, table, insert) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/orm/persistence.py", line 570, in _emit_insert_statements execute(statement, multiparams) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 729, in execute return meth(self, multiparams, params) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 321, in _execute_on_connection return connection._execute_clauseelement(self, multiparams, params) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 826, in _execute_clauseelement compiled_sql, distilled_params File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 958, in _execute_context context) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1160, in _handle_dbapi_exception exc_info File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause reraise(type(exception), exception, tb=exc_tb) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 951, in _execute_context context) File "/home/plannotate/.virtualenvs/P2v0.0.1/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 436, in do_execute cursor.execute(statement, parameters) IntegrityError: (IntegrityError) duplicate key value violates unique constraint "pbases_history_pkey" DETAIL: Key (id, version)=(125, 21) already exists. ####### MODEL The simplified version of our model looks like this: class PBase(Versioned, Base): __tablename__ = 'pbases' id = Column(Integer, primary_key=True) uuid = Column(String(50), unique=True) classname = Column(String(50)) __mapper_args__ = { 'polymorphic_identity' : 'PBase', 'polymorphic_on' : classname } class PDocument(PBase): __tablename__ = 'pdocuments' id = Column(Integer, ForeignKey('p2bases.id'), primary_key=True) name = Column(String) __mapper_args__ = { 'polymorphic_identity' : 'P2Document', } class PNote(PBase): __tablename__ = 'pnotes' id = Column(Integer, ForeignKey('p2bases.id'), primary_key=True) comment = Column(String) position = Column(Integer) document_id = Column(Integer, ForeignKey('p2documents.id')) document_version = Column(Integer, default=0) document = relationship("PDocument", primaryjoin="PDocument.id == PNode.document_id", backref=backref('pages', order_by= "PNode.position", collection_class=ordering_list('position'))) __mapper_args__ = { 'polymorphic_identity' : 'PNote', } @event.listens_for(PNode.document_id, 'set', active_history=True) def _on_note_set_document_id(note, new_doc_id, old_old_id, initiator): doc = None if new_doc_id: doc = DBSession.query(PDocument).filter(PDocument.id == new_doc_id).one() elif old_doc_id: page = DBSession.query(PDocument).filter(PDocument.id == old_doc_id).one() if doc: note.document_version = doc.version ####### SYSTEM CONFIG PostgreSQL 9.3.5 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-bit argparse (1.2.1) beautifulsoup4 (4.3.2) Chameleon (2.16) colander (1.0b1) cornice (0.17) coverage (3.7.1) Mako (1.0.0) MarkupSafe (0.23) nose (1.3.4) p2server (0.0) PasteDeploy (1.5.2) pip (1.5.6) psycopg2 (2.5.4) Pygments (1.6) pyramid (1.5.1) pyramid-chameleon (0.3) pyramid-debugtoolbar (2.2) pyramid-mako (1.0.2) pyramid-tm (0.7) repoze.lru (0.6) requests (2.4.3) setuptools (3.6) simplejson (3.6.4) six (1.8.0) SQLAlchemy (0.9.7) transaction (1.4.3) translationstring (1.1) venusian (1.0) waitress (0.8.9) WebOb (1.4) WebTest (2.0.16) wsgiref (0.1.2) zope.deprecation (4.1.1) zope.interface (4.1.1) zope.sqlalchemy (0.7.5) -- 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.