当前位置: 首页 > 面试题库 >

如何在多线程Python应用程序中共享单个SQLite连接

匡安宜
2023-03-14
问题内容

我正在尝试编写一个多线程Python应用程序,其中在线程之间共享一个SQlite连接。我无法使它正常工作。真正的应用程序是一个小巧的Web服务器,但是以下简单代码演示了我的问题。

为了成功运行下面的示例代码,我需要进行哪些更改?

当我在THREAD_COUNT设置为1的情况下运行此程序时,它可以正常工作,并且数据库已按预期进行更新(即,字母“
X”被添加到SectorGroup列的文本值中)。

当我将THREAD_COUNT设置为大于1的任何值运行它时,除1以外的所有线程都会因SQLite相关异常而提前终止。不同的线程抛出不同的异常(没有可识别的模式),包括:

OperationalError: cannot start a transaction within a transaction

(发生在UPDATE声明上)

OperationalError: cannot commit - no transaction is active

(发生在.commit()调用上)

InterfaceError: Error binding parameter 0 - probably unsupported type.

(发生在UPDATESELECT语句上)

IndexError: tuple index out of range

(这让我完全感到困惑,它发生在语句上group = rows[0][0] or '',但仅在运行多个线程时才发生)

这是代码

CONNECTION = sqlite3.connect('./database/mydb', detect_types=sqlite3.PARSE_DECLTYPES, check_same_thread = False)
CONNECTION.row_factory = sqlite3.Row

def commands(start_id):

    # loop over 100 records, read the SectorGroup column, and write it back with "X" appended.
    for inv_id in range(start_id, start_id + 100):

        rows = CONNECTION.execute('SELECT SectorGroup FROM Investment WHERE InvestmentID = ?;', [inv_id]).fetchall()
        if rows:
            group = rows[0][0] or ''
            msg = '{} inv {} = {}'.format(current_thread().name, inv_id, group)
            print msg
            CONNECTION.execute('UPDATE Investment SET SectorGroup = ? WHERE InvestmentID = ?;', [group + 'X', inv_id])

        CONNECTION.commit()

if __name__ == '__main__':

    THREAD_COUNT = 10

    for i in range(THREAD_COUNT):
        t = Thread(target=commands, args=(i*100,))
        t.start()

问题答案:

在线程之间共享连接是不安全的。至少您需要使用锁来序列化访问。还要阅读http://docs.python.org/2/library/sqlite3.html#multithreading,因为较旧的SQLite版本仍然存在更多问题。

check_same_thread在这方面,该选项故意未充分记录在文档中,请参阅http://bugs.python.org/issue16509。

您可以改为每个线程使用一个连接,也可以使用SQLAlchemy作为连接池(以及用于引导的非常有效的工作陈述和排队系统)。



 类似资料:
  • 我注意到一些web框架(如Play Framework)允许您配置多个不同大小的线程池(线程池中的线程数)。假设我们在单核的单机中运行这个游戏。拥有多个线程池不会有很大的开销吗?

  • 问题内容: 我们遇到了适用于多线程的方案。 在主线程中,执行一些逻辑操作并更新数据库,在某种程度上,它将调用另一个服务来更新数据库,该服务在另一个线程中运行。 我们希望两个线程共享同一个事务,这意味着任何一个线程中的任何一个操作都将失败,那么另一个线程中的该操作也将被回滚。 但是工作了几天,我发现一些帖子说JTA不支持多线程。当前我们使用Bitronix作为JTA提供者,有没有人知道Bitroni

  • 我将Spring缓存与CacheManager结合使用,并可在10个不同的应用程序中缓存同一表中的相同数据。实现时的假设是,我们缓存的数据是元数据,不应更改。然而,他们正在更改这些数据,缓存永远不会被清除。 现在的要求是通过2个大请求同时清除所有10个应用程序的缓存。 每当mySQL工作台上的直接INSERT语句更改表时,所有应用程序缓存都应该刷新。我使用的是Hibernate和Spring,但请

  • 问题内容: 我正在尝试将Hibernate用于多线程应用程序,其中每个线程都检索一个对象并将其插入表中。我的代码如下所示。我每个线程都有本地hibernate会话对象,在每个InsertData中,我都执行beginTransaction和commit。 我面临的问题是很多次我收到“ org.hibernate.TransactionException:不支持嵌套事务” 由于我是hibernate

  • 问题内容: 是否有一种实际的方法可以在PHP中实现多线程模型,无论是真正的还是仅对其进行仿真。一段时间以前,建议您可以强制操作系统加载PHP可执行文件的另一个实例并处理其他同时进行的进程。 这样做的问题是,当PHP代码完成执行PHP实例后,它仍保留在内存中,因为无法从PHP中杀死它。因此,如果您正在模拟多个线程,则可以想象会发生什么。因此,我仍在寻找一种可以在PHP中有效完成或模拟多线程的方法。有

  • 问题内容: 我正在用Python开发一个固有的多线程模块,我想找出它在哪里花时间。cProfile似乎仅分析主线程。有什么方法可以分析计算中涉及的所有线程? 问题答案: 请参阅yappi(另一个Python Profiler)。