插入期间出现SQLite错误“试图编写只读数据库”?


123

我有一个用于网站的SQLite数据库。问题是当我尝试INSERT INTO时,会得到一个PDOException

SQLSTATE[HY000]: General error: 8 attempt to write a readonly database

我通过SSH进入服务器并检查了权限,数据库具有该权限

-rw-rw-r--

我对* nix权限不太熟悉,但是我很确定这意味着

  • 不是目录
  • 所有者拥有读/写权限(根据,就是我ls -l
  • 组具有读/写权限
  • 其他所有人仅具有读取权限

我也浏览了我知道使用该sqlite3程序的所有地方,但没有发现任何相关信息。

因为我不知道PDO试图以什么权限打开数据库,所以我做了

chmod o+w supplies.db

现在,我得到另一个PDOException

SQLSTATE[HY000]: General error: 14 unable to open database file

但是它仅在打开数据库尝试执行INSERT查询时才会发生。

有什么想法吗?


基本上httpd(apache> php> PDO)不是您,因此它不拥有该文件,因此它没有写权限...有趣的是
SparK 2012年

sudo chgrp www-data test.db添加权限为我工作
Zippp

Answers:


305

这个问题,因为它的出现,就是PDO SQLite的驱动程序要求,如果你打算做一个写操作(INSERTUPDATEDELETEDROP,等),然后将文件夹的数据库驻留在必须有写权限,以及实际数据库文件。

在PDO SQLite驱动程序手册页最底部的注释中找到了此信息。


9
另外,不得强制执行SELinux(如果已安装)。花了我一天半的时间弄清楚那个。
史蒂夫五世

1
哼,对不起,但是我很感谢,但这只是暂时解决了这个问题,主要的问题是我的www-data用户不在www-data组中。
多利安

5
据我所知,包含文件夹必须是可写的,因为在编写日志文件时将创建数据库本身。要具有与Web服务器相同的用户,请尝试将文件内容复制到另一个创建的临时文件中。
lcapra 2011年

4
db文件及其所在的目录也必须由Linux机器上的“ www-data”拥有。
anisbet

1
当前,sqlite3可能具有3个文件,,.dba .db-shm和a .db-wal文件,当然还有这3个文件的父目录,运行该程序的用户必须都可写这些目录。
Marcos Dione

17

当SQLite文件本身的所有者与运行脚本的用户同时,可能会发生这种情况。如果无法写入整个目录路径(即沿途的每个目录),则可能会发生类似的错误。

谁拥有SQLite文件?您?

脚本以谁身份运行?Apache还是没人?


1
我拥有SQLite文件,但我不知道脚本的运行身份。我怎么知道?(请记住,这是在共享主机上,并且我具有有限的权限)
奥斯汀·海德

1
嗯,这使事情变得更加有趣。如果您使用共享主机,则脚本很有可能以“ nobody”或“ apache”的身份运行。让您的脚本创建一个文件(file_put_contents('./foo.txt', 'Hello, world');),该文件将向您显示运行的文件名。您可能需要让脚本创建SQLite数据库。如果您当前的文件中已经有数据,这可能是一个有趣的练习……
查尔斯(Charles)2010年

好主意,但是不行。谁运行的PHP都没有写权限,所以无法创建文件。无论如何,PHP可以检索其当前运行身份的用户吗?
奥斯丁·海德

唯一的方法似乎是通过POSIX扩展名,该扩展名在POSIX-y系统上默认启用。不过,您的托管服务提供商可能拥有R'd TFM并将其禁用。
查尔斯

好吧,他们是TFM,好的。posix_getuid()也不起作用。
奥斯汀·海德

6

对我而言,问题在于SELinux的实施而非许可。一旦我禁用了强制执行功能, “只读数据库”错误就消失了,这是史蒂夫五世在对已接受答案的评论中提出的建议

echo 0 >/selinux/enforce

运行此命令后,一切按预期进行(CentOS 6.3)。

我遇到的特定问题是在Graphite的安装过程中。我已对apache用户拥有的内容进行了三重检查,并且可以同时写入我的graphite.db及其父目录。但是直到我“修复” SELinux之前,我得到的只是堆栈跟踪,以达到以下效果:DatabaseError:尝试编写一个只读数据库


8
SELinux是一种安全措施,因此如果没有很好的理由,则不应禁用它。最好弄清楚为什么SELinux首先会阻塞并正确配置它而不是禁用它。
Jens Wegar 2014年

5

这可能是由SELinux引起的。如果不想完全禁用SELinux,则需要将db目录fcontext设置为httpd_sys_rw_content_t。

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/railsapp/db(/.*)?"
restorecon -v /var/www/railsapp/db

4

当我尝试写入Android系统上的数据库时出现此错误。

显然,sqlite3不仅需要对数据库文件和包含目录的写权限(如@ austin-hyde在其回答中已经说过的),而且环境变量TMPDIR还必须指向(可能是可写的)目录。

在我的Android系统上,将其设置为TMPDIR="/data/local/tmp",现在我的脚本按预期方式运行:)

编辑:

如果您无法设置环境变量,则可以使用此处列出的其他方法之一:https : //www.sqlite.org/tempfiles.html#temporary_file_storage_locations likePRAGMA temp_store_directory = 'directory-name';


2

我在Windows 7下从IIS得到了相同的错误。要解决此错误,我必须为sqlite数据库文件的IUSR帐户添加完全控制权限。如果在webmatrix下而不是IIS下使用sqlite,则无需更改权限。


2

总之,我通过将数据库文件(* .db)放在子文件夹中来解决此问题。

  • 子文件夹和其中的数据库文件必须是www-data组的成员。
  • 在www-data组中,您必须有权写入子文件夹和数据库文件。


0

我用了:

echo exec('whoami');

找出谁在运行脚本(例如用户名),然后向用户授予整个应用程序目录的权限,例如:

须藤chown -R:用户名/ var / www / html / myapp

希望这可以帮助某人。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.