[Sqlalchemy-tickets] Issue #3947: race condition in joined eager load perf enhancement (zzzeek/sqla
Brought to you by:
zzzeek
From: Michael B. <iss...@bi...> - 2017-03-26 00:19:58
|
New issue 3947: race condition in joined eager load perf enhancement https://bitbucket.org/zzzeek/sqlalchemy/issues/3947/race-condition-in-joined-eager-load-perf Michael Bayer: e.g. #3915 test: ``` #!python from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class A(Base): __tablename__ = 'a' id = Column(Integer, primary_key=True) bs = relationship("B") class B(Base): __tablename__ = 'b' id = Column(Integer, primary_key=True) a_id = Column(ForeignKey('a.id')) e = create_engine("sqlite:///foo.db", echo=False) Base.metadata.create_all(e) import threading import random import time import traceback def work(e): s = Session(e) while True: try: s.query(A).options(joinedload(A.bs)).all() except Exception as e: traceback.print_exc() print "Exception: %s" % e finally: time.sleep(random.random()) def chaos(): while True: time.sleep(.001) A.bs.property._get_strategy((("lazy", "joined"),))._aliased_class_pool[:] = [] s = Session(e) s.add_all([A(bs=[B(), B(), B()])]) s.commit() threads = [threading.Thread(target=work, args=(e, )) for i in range(20)] chaos = threading.Thread(target=chaos) for t in threads: t.start() chaos.start() ``` traceback ``` #! Traceback (most recent call last): File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 2679, in all File "test.py", line 31, in work s.query(A).options(joinedload(A.bs)).all() File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 2679, in all yes return list(self) return list(self) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/loading.py", line 90, in instances File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 2831, in __iter__ return self._execute_and_instances(context) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 2854, in _execute_and_instances result = conn.execute(querycontext.statement, self._params) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 945, in execute util.raise_from_cause(err) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/util/compat.py", line 203, in raise_from_cause reraise(type(exception), exception, tb=exc_tb, cause=cause) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/loading.py", line 57, in instances for query_entity in query._entities File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/query.py", line 3686, in row_processor polymorphic_discriminator=self._polymorphic_discriminator File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/loading.py", line 330, in _instance_processor context, path, mapper, result, adapter, populators) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/interfaces.py", line 532, in create_row_processor return meth(self, multiparams, params) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/elements.py", line 269, in _execute_on_connection mapper, result, adapter, populators) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/strategies.py", line 1594, in create_row_processor eager_adapter) return connection._execute_clauseelement(self, multiparams, params) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/loading.py", line 318, in _instance_processor File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement col = adapter.columns[col] compiled_sql, distilled_params File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/sql/util.py", line 713, in __getitem__ File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1189, in _execute_context context) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1393, in _handle_dbapi_exception exc_info File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/util/compat.py", line 203, in raise_from_cause reraise(type(exception), exception, tb=exc_tb, cause=cause) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/engine/base.py", line 1182, in _execute_context context) self.parent.include_fn and not self.parent.include_fn(key) File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/orm/util.py", line 326, in _include_fn File "/home/classic/dev/sqlalchemy/lib/sqlalchemy/engine/default.py", line 504, in do_execute entity = elem._annotations.get('parentmapper', None) AttributeError: 'NoneType' object has no attribute '_annotations' Exception: 'NoneType' object has no attribute '_annotations' cursor.execute(statement, parameters) ``` |