我正在DBD::SQLite访问的Perl CGI脚本中运行SQLite数据库。它正在Apache上作为直接CGI运行。
DBI连接可以正常工作,并且可以运行选择。但是,当我尝试插入时,出现以下错误:
DBD::SQLite::st execute failed: unable to open database file(1) at dbdimp.c line 402 at index.cgi line 66
我已经尝试将数据库文件权限更改为666,以尝试解决此问题,但是我仍然收到错误。
有什么建议吗?
看起来目录需要写权限,原因是:
SQLite必须能够在与数据库相同的目录中创建日记文件,然后才能进行任何修改。该日志用于支持事务回滚。
SQLite在执行插入和更新时会暂时锁定整个文件(没有这样的记录级锁定)。您确定要释放锁吗?
SQLite文献建议您启动事务,在该事务中收集所有插入和更新,然后再提交。这样可以避免大量连续的文件锁定,并提高了性能。
由于SQLite锁定了整个数据库文件,因此您可能希望使用基于超时的重试机制。当我问这个相关的question时,我正在处理几乎相同的问题。
我最终写出了类似于Mark Fowler的Attempt的东西,如果子程序抛出的异常与正则表达式匹配,则重试qr(already in a transaction|database is locked)i
:
journal_mode
db文件所在目录的路径应同时设置可执行位和可写位,以便从脚本中访问它。此外,如果您不希望直接访问db文件(即使不使用特殊的服务器文件),它也应具有600的访问权限,并且不应该直接浏览包含目录(同样,即使没有使用特殊的服务器文件),它应该具有700的访问权限。我使用此设置,并且在本地以及托管我的网站的服务器上都可以正常工作。当然,如果其中包含任何其他文件可以通过html,css或javascript访问,则包含目录的权限不能为700。应该是755。
如果您不想按照Todd Hunter的回答中所述对整个目录设置写权限,则可以将journal_mode
PRAGMA设置为“ MEMORY”。
在这种情况下,请注意:
MEMORY日记记录模式将回滚日记存储在volatile中内存。这样可以节省磁盘I / O,但要以牺牲数据库安全性和诚信。如果使用SQLite的应用程序在中间崩溃设置MEMORY日记记录模式时进行事务处理,然后数据库文件很可能会损坏。
因此,这是否是一个好的解决方案,取决于您的数据库及其使用方式。
[其他人也提到temp_store pragma。我不需要进行设置,但这可能取决于数据库的使用方式。
因此,在您的Perl CGI脚本中,您可以尝试以下操作:
$dbh->do("PRAGMA journal_mode = MEMORY");
$dbh->do("PRAGMA temp_store = MEMORY");