【问题标题】:Database locking issue with QSqlTableModelQSqlTableModel 的数据库锁定问题
【发布时间】:2021-11-22 05:17:43
【问题描述】:

我正在开发一个 PyQt 应用程序,它使用 QTableViewQSqlTableModel 显示来自 SQLite 数据库的数据。主视图设计为只读。用户可以启动编辑器来编辑数据库中的值。编辑器使用sqlite3 在数据库中进行更改。 (由于 Qt 在 C++ 和 Python 之间的类型转换很尴尬,我不想在编辑器中使用 Qt 数据库 API)。

我的问题:尝试在编辑器中更改数据库时,我收到sqlite3.OperationalError: database is locked。我设法弄清楚这是由于QTableView 由于其延迟获取特性而在数据库上持有锁(它只获取 256 行,然后在数据库连接上留下锁)。更多信息请访问this link

我想出了以下解决方案:

  • 在启动编辑器之前关闭 Qt 数据库连接 - 不理想,因为它会阻止主窗口在编辑器打开时工作
  • 在启动编辑器之前清除 QSqlTableModel 实例 - 与上述相同的问题
  • 在启动编辑器之前使用QSqlTableModel.fetchMore()获取所有数据-这似乎释放了锁定,但如果主窗口仍然可以操作,我想锁定可以随时重新建立,防止进一步写入?
  • 通过子类化 QSqlTableModelQAbstractItemModel 创建一个新类并自己控制锁定

在我选择最后一个之前,有没有更简单的选择?

【问题讨论】:

  • “尴尬的类型转换”到底是什么意思,我相信您可以使用QItemDelegate 覆盖它们。
  • @mugiseyebrows 我发现如果您的数据库中有 NULL,PyQt 会将它们作为空字符串返回,并且您无法再将它们与数据库中的实际空字符串区分开来。这是因为 C++ QtVariant 类型被“智能”地自动转换为 Python 类型。这可以解决,但这足以阻止我使用 PyQt 数据库 API。 (另外,使用sqlite3 会产生更好的代码)。
  • 使用两个连接而不是一个连接并重写 QSqlTable 中已有的内容(更新和缓存),这反过来又会造成复杂性,对我来说似乎不是很好的代码。
  • SQLite 是一个很棒的工具,既快速又轻量。但它不能很好地支持对同一个数据库的多次访问。恕我直言,您在这里有一个主要的一般设计问题。它可以通过使用更重的数据库引擎(如 PostgreSQL 或 MariaDB)来解决,或者让编辑器不直接访问数据库,或者......但是让多个进程访问同一个 SQLite 数据库可能会成为维护噩梦的根源...... .
  • @JussiNurminen NULL 值的问题可以很容易地解决,这在 PyQt 文档中进行了解释:Support for QVariant。简而言之,您可以像这样抑制自动转换:sip.enableautoconversion(QVariant, False); ... # do stuff that returns variant values ...; sip.enableautoconversion(QVariant, True)。这将暂时将值作为包装的 QVariant 而不是 python 类型返回,因此您可以使用 value.isNull() 等。

标签: python sqlite pyqt


【解决方案1】:

我最终以以下方式继承了QSqlTableModel。它似乎可以防止发生锁定。

class NonLazyQSqlTableModel(QtSql.QSqlTableModel):
    """QSqlTableModel without the prefetch feature.

    This works for small tables. The purpose is to prevent SQL locking that
    occurs with prefetch.
    """

    def fetchMore(self, parent: QtCore.QModelIndex = ...) -> None:
        """Whenever fetchMore is called, we fetch everything"""
        while super().canFetchMore():
            super().fetchMore()

【讨论】:

    猜你喜欢
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 2010-10-29
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多