使用 SQLite 的 CGI 程序出现不一致的“无法打开数据库文件”错误

使用 SQLite 的 CGI 程序出现不一致的“无法打开数据库文件”错误

我一直在奔跑心理学实验的任务程序在我的虚拟专用服务器上,使用 lighttpd 1.4.28 和 Ubuntu 12.04。实验是一个用 Perl 编写的 CGI 程序,使用我编写的 Perl 模块,通过 Mechanical Turk 呈现 Web 界面。数据使用 WAL 模式存储在 SQLite 数据库中,DBD::SQLite 提供底层 Perl 接口。

对于在 Mechanical Turk 上完成实验的大多数工作者来说,实验似乎运行良好。然而,偶尔用户会遇到错误DBD::SQLite::db prepare failed: unable to open database file。它似乎发生在任务进行到一半的任意点,该任务涉及点击由 CGI 程序生成的大约 100 个 HTML 页面,每个页面都会访问数据库。当用户刷新页面时,它似乎不会消失(我思考)。我不知道如何自己复制它,但我知道它至少影响了 15 个用户中的 2 个。在top发生这种情况时,CPU 和内存似乎没有受到压力。磁盘空间也不是问题(我只使用了 3 GB 分区中的 1.4 GB)。数据库目前大约为 280 kb。PRAGMA integrity_check;返回ok

有什么想法可以调试这个问题吗?Google 告诉我“无法打开数据库文件”通常是权限错误或类似错误,但所有设置均正确;任务通常可以正常工作。

答案1

当 SQLite 无法创建临时文件时,可能会发生此错误。(在这种情况下,错误消息中的“数据库文件”有点误导。)

例如,如果 SQLite 需要将临时表/索引写入磁盘,并且未设置环境变量 TMP、TEMP、USERPROFILE,则在 Windows 上会发生这种情况。在这种情况下,SQLite 会尝试在 Windows 目录中创建临时文件,这通常是不允许的。可以通过将 TEMP 传递给脚本(在 Apache 配置中PassEnv "TEMP"),或在脚本内部指向$ENV{TEMP}合适的目录来修复此问题。

临时文件创建可能会因其他原因而失败。请参阅 SQLite 源中的函数“unixGetTempname”和“winGetTempname”,了解 SQLite 用于在您的平台上查找临时目录的确切规则。

相关内容