当使用连接池时,SQLAlchemy键错误。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当使用连接池时,SQLAlchemy键错误。相关的知识,希望对你有一定的参考价值。

我为Person创建了一个存储库类,里面有下面的方法。

def find_by_order_id(self, order_id: str) -> [Person]:
    results = []

    client_table = Table(TBL_CLIENT, self._metadata, autoload=True,
                             autoload_with=self._connection)
    order_table = Table(TBL_ORDER, self._metadata, autoload=True,
                             autoload_with=self._connection)

    query = select([client_table.c.first_name, client_table.c.last_name, client_table.c.date_of_birth])
    .select_from(
        order_table.join(client_table, client_table.c.order_id = order_table.c.order_id)
    ).where(order_table.c.order_id == order_id).distinct()

    for row in self._connection.execute(query).fetchall():
        results.append(dict(row))

    return results

由于一些我无法解释的奇怪原因,当我调试代码时,我有时会从SQLAlchemy那里得到一个实际存在的keyError。

File "/home/tghasemi/miniconda3/envs/myproj/lib/python3.6/site-packages/sqlalchemy/util/_collections.py", line 210, in __getattr__
    return self._data[key]
KeyError: 'order_id'

我注意到这种情况只发生在多线程时从连接池中提取连接时(每个线程只使用一个连接--我知道连接不是线程安全的)。

if use_pooling:
        self._engine = create_engine(connection_string, pool_size=db_pool_size,
                                     pool_pre_ping=db_pool_pre_ping, echo=db_echo)
else:
        self._engine = create_engine(connection_string, echo=db_echo)

考虑到当我在异常发生的地方设置一个断点时,键是存在的(甚至在异常发生时也检查了它),我怀疑在构建查询时,表的加载还没有完成。

有人知道为什么会发生这样的事情吗? 我放弃了!

答案

好吧,我想我设法解决了这个问题。

我在我的问题中没有提到的东西(事实上,我没有想到它的可能性)是引擎和MetaData对象都来自于我为数据库创建的Singleton类。

class Database(metaclass=SingletonMetaClass):

    def __init__(self, config: Config, use_pooling: bool = True, logger: Logger = None):
        # Initializing the stuff here ...


    @property
    def metadata(self): # used to return self._metadata here 
        return MetaData(self._engine, reflect=False, schema=self._db_schema)

    @property
    def engine(self):
        return self._engine

尽管SQLAlchemy的官方文档说MetaData对象对读操作是线程安全的,但由于某些原因,在我的情况下(这是一个读操作),它导致了这个问题。不知道为什么,在我的线程之间不共享这个对象后,问题就消失了(不是100%确定是否真的消失了,但现在不再发生了)。

以上是关于当使用连接池时,SQLAlchemy键错误。的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 SQLAlchemy 捕获完整性错误

sqlalchemy 1.1.10 oracle连接错误

尝试连接数据库和 Web 容器时 SQLAlchemy 连接被拒绝

Flask-SqlAlchemy - 与列''关联的外键无法找到表

sqlalchemy 使用pymysql连接mysql 1366错误

sqlalchemy 使用pymysql连接mysql 1366错误