为什么我的Perl CGI脚本不能通过DBD::SQLite插入数据库?

11

我正在运行一个SQLite数据库,它是由Perl CGI脚本访问的,使用的是DBD::SQLite。该脚本在Apache上直接运行。

DBI连接正常,在此可以运行选择命令。但是,在我尝试插入数据时,会出现以下错误:

DBD::SQLite::st execute failed: unable to open database file(1) at dbdimp.c line 402 at index.cgi line 66

我尝试将数据库文件的权限更改为666以尝试解决这个问题,但我仍然收到错误提示。

有什么建议吗?


1
你能否将目录和文件权限暂时设置为777并重新检查一下吗? - Henrik P. Hessel
啊哈!将目录权限更改为777解决了这个问题。你知道为什么吗? - Todd Hunter
你可能也忘记设置正确的目录权限了。 - Henrik P. Hessel
5个回答

23

1

由於SQLite會鎖定整個數據庫文件,因此您可能希望使用基於超時的重試機制。當我提出這個相關的問題時,我正在解決幾乎相同的問題。

最終,我寫了一些類似於Mark Fowler的Attempt的東西,如果子程序拋出的異常匹配正則表達式,則進行重試,在我的情況下:

qr(already in a transaction|database is locked)i

1

访问脚本中的数据库文件所在目录的路径应该同时设置可执行和可写位,以便访问它。

此外,如果您不希望直接访问数据库文件(即使没有使用特殊服务器文件),它应该具有诸如600之类的访问权限,如果包含目录不应直接浏览(同样,即使没有使用特殊服务器文件),它应该具有诸如700之类的访问权限。

我使用这个设置,在本地和托管我的网站的服务器上都可以正常工作。

当然,如果存在任何其他文件可以通过html、css或javascript访问,则包含目录的权限不能为700。它应该是755。


1

SQLite在进行插入和更新时会暂时锁定整个文件(实际上没有记录级别的锁定)。 您确定您释放了锁定吗?

SQLite文献建议您启动一个事务,收集所有今天的插入和更新,在该事务中进行,然后提交。 这可以避免多次连续的文件锁定并提高性能。


0

如果您不想像Todd Hunter的回答中所解释的那样在整个目录上设置写入权限,您可以将journal_mode PRAGMA设置为"MEMORY"。

在这种情况下,请注意:

MEMORY日志模式将回滚日志存储在易失性RAM中。这样可以节省磁盘I/O,但会牺牲数据库的安全性和完整性。如果在设置了MEMORY日志模式的情况下,使用SQLite的应用程序在事务进行中崩溃,则数据库文件很可能会损坏。

因此,这是否是一个好的解决方案取决于您的数据库以及它的使用方式。

其他人还提到了temp_store pragma。我不需要设置它,但这可能取决于数据库的使用方式。

因此,在您的Perl CGI脚本中,您可以尝试这样做:

$dbh->do("PRAGMA journal_mode = MEMORY");
$dbh->do("PRAGMA temp_store   = MEMORY");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接