0

直到昨天,我还在为我的应用程序使用 SQLite。今天我找到了一个足够强大的理由(应用程序的多个实例)来使用pymysql.

有一次,我的应用程序在数据库中查询 300 行:

cur.execute('select ime,brPredmeta,statusStr,sudskiBr ,sudija ,datumRasprave,statusPredmeta, zaduzen,datumZaduzenja from predmeti')
sviaktivni = cur.fetchall()
sviaktivni = list(sviaktivni) #make a list of tuples
sviaktivni.sort(key=operator.itemgetter(0)) #sort the list

之后,我提取变量,然后使用这些变量制作 HTML 文档,然后将其发送到打印机(PDF 或普通打印机)。生成 HTML 的代码非常简单;“标题”的几行表(为清楚起见此处省略),然后是“正文”的另一个表,代码如下:

#extract the variables
for tuple in sviaktivni:
    ime,brPredmeta,statusStr,sudskiBr ,sudija ,datumRasprave,statusPredmeta, zaduzen,datumZaduzenja = tuple
#done extracting

  body = ('<html><head><title></title>'
    '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>'
    '<style></style>'
    '</head>'
    '<body>'
    '<table align ="center" border="0" width="100%" style="table-layout:fixed">'
    '<tr height="10%">'
    '<td align="left" width="20">'+str(brojac)+'.</td>'
    '<td align="left" width="180">'+ime+'</td>'
    '<td align="left" width="100">'+str(brPredmeta)+'</td>'
    '<td align="left" width="80">'+statusStr+'</td>'
    '<td align="left" width="80">'+str(sudskiBr)+'</td>'
    '<td align="left" width="140">'+sudija+'</td>'
    '<td align="left" width="150">'+zaduzen+'</td>'
    '<td align="left">'+datumZaduzenja+'</td>'
    '<td align="right"> '+statusPredmeta+' </td>'
    '</tr>'
    '</table>'
    '</body>'
    '</html>')

  self.ui.printHTML.append(body)

我的问题是查询立即执行,但之后 CPU 卡在 100%,整个程序就冻结了。打印预览对话框有时会显示数据,有时它只是一个空窗口。无论哪种方式,整个应用程序都被冻结。

使用 SQLite 的相同代码没有问题。我应该怎么办?回到 sqlite 并冒着数据库损坏的风险?

4

2 回答 2

1

不要只是将整个 SQL 结果加载到内存中,并期望这适用于所有情况。而且,使用数据库为您进行排序,这是它擅长的。

只需循环游标并逐一处理结果,这样您就不必用中间结果填满内存:

cur.execute('''
    select 
        ime, brPredmeta, statusStr, sudskiBr, sudija,
        datumRasprave,statusPredmeta, zaduzen,datumZaduzenja
    from predmeti
    order by ime
    ''')
for row in cur:
    ime, brPredmeta, statusStr, sudskiBr, sudija, datumRasprave, statusPredmeta, zaduzen, datumZaduzenja = row
    # Process row data.
于 2012-09-04T12:29:35.940 回答
0

取自 SQLite 文档...

多个应用程序或同一应用程序的多个实例可以同时访问单个数据库文件吗?

多个进程可以同时打开同一个数据库。多个进程可以同时执行 SELECT。但是,任何时候只有一个进程可以对数据库进行更改。

SQLite 使用读/写锁来控制对数据库的访问。(在不支持读/写锁的 Win95/98/ME 下,改为使用概率模拟。)但请注意:如果数据库文件保存在 NFS 文件系统上,此锁定机制可能无法正常工作。这是因为 fcntl() 文件锁定在许多 NFS 实现中被破坏。如果多个进程可能尝试同时访问该文件,则应避免将 SQLite 数据库文件放在 NFS 上。在 Windows 上,Microsoft 的文档说如果您没有运行 Share.exe 守护程序,锁定可能无法在 FAT 文件系统下工作。对 Windows 有很多经验的人告诉我,网络文件的文件锁定非常有问题,而且不可靠。如果他们说的是真的,

我们知道没有其他嵌入式 SQL 数据库引擎支持与 SQLite 一样多的并发性。SQLite 允许多个进程一次打开数据库文件,并允许多个进程一次读取数据库。当任何进程想要写入时,它必须在其更新期间锁定整个数据库文件。但这通常只需要几毫秒。其他流程只是等待作者完成,然后继续他们的业务。其他嵌入式 SQL 数据库引擎通常只允许单个进程一次连接到数据库。

但是,客户端/服务器数据库引擎(例如 PostgreSQL、MySQL 或 Oracle)通常支持更高级别的并发性,并允许多个进程同时写入同一个数据库。这在客户端/服务器数据库中是可能的,因为始终有一个受良好控制的服务器进程可用于协调访问。如果您的应用程序需要大量并发,那么您应该考虑使用客户端/服务器数据库。但经验表明,大多数应用程序需要的并发性远低于其设计者的想象。

当 SQLite 尝试访问被另一个进程锁定的文件时,默认行为是返回 SQLITE_BUSY。您可以使用 sqlite3_busy_handler() 或 sqlite3_busy_timeout() API 函数从 C 代码调整此行为。

于 2012-09-04T09:47:15.540 回答