SQLite 错误“试图在插入过程中写入只读数据库”?

我有一个 SQLite 数据库,我正在使用一个网站。问题是,当我尝试 INSERT INTO它,我得到一个 PDOException

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

我 SSH 到服务器和检查权限,数据库有权限

-rw-rw-r--

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

  • 不是目录
  • Owner 拥有读/写权限(根据 ls -l,这是我的权限)
  • 组具有读/写权限
  • 其他人只有读权限

我也找遍了所有我知道的使用 sqlite3程序的地方,没有发现任何相关的东西。

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

chmod o+w supplies.db

现在,我得到另一个 PDOException:

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

但只有当我尝试执行 INSERT查询 之后时,数据库才会打开。

知道是怎么回事吗?

204528 次浏览

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

谁拥有 SQLite 文件? 你吗?

脚本是以谁的身份运行的? 阿帕奇还是无名氏?

问题在于,PDO SQLite 驱动程序要求,如果您要执行写操作(INSERTUPDATEDELETEDROP等) ,那么数据库所在的文件夹必须具有写权限,以及实际的数据库文件。

我在 注释在 PDO SQLite 驱动程序手册页的最底部里找到了这个信息。

对我来说,问题是 SELinux 执法部门而不是权限。“只读数据库”错误消失后,我 残疾执法人员,的建议后,由史蒂夫 V 在评论 公认的答案。

echo 0 >/selinux/enforce

在运行这个命令时,一切都按预期运行(CentOS 6.3)。

我遇到的具体问题是在设置石墨。我已经三次检查了 apache 用户是否拥有并且可以写入我的 Graphite.db 及其父目录。但是在我“修复”SELinux 之前,我得到的只是一个栈跟踪,效果是: DatabaseError: 尝试写入只读数据库

我在 Windows7下的 IIS 中得到了同样的错误。为了修复这个错误,我必须为 sqlite 数据库文件的 IUSR 帐户添加完全控制权限。如果在 webMatrix 下使用 sqlite 而不是 IIS,则不需要更改权限。

当我从使用 http://localhost改为使用 http://145.900.50.20(其中145.900.50.20是我的本地 IP 地址) ,然后又改回本地主机时,我在浏览器中得到了这个地址——一旦我改变了一次,就必须保留这个 IP 地址

这可能是 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

当我试图在 Android 系统上写入数据库时,我得到了这个错误。

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

在我的 Android 系统上,我将它设置为 TMPDIR="/data/local/tmp",现在我的脚本运行正常:)

编辑:

如果你不能设置环境变量,你可以使用这里列出的其他方法: < a href = “ https://www.sqlite.org/temfiles.html # Clinical _ file _ Storage _ location”rel = “ nofollow norefrer”> https://www.sqlite.org/tempfiles.html#temporary_file_storage_locations 就像 PRAGMA temp_store_directory = 'directory-name';

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

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

类似问题的附加说明

我将 sqlite 数据库文件的写权限授予了其他用户和组,但它仍然不起作用。

文件位于我的.NETCoreWebApi 的 web 根目录中。

它看起来像这样:

-rw-rw-rw-  1 root root  24576 Jan 28 16:03 librestore.db

即使我以 root 用户身份运行这个服务,我仍然会得到这样的错误:

错误: SQLite 错误8: “尝试写入只读数据库”。

我还查看了 librestore.db 上的 www-data,仍然收到相同的错误。

最后,我移动到我的 webroot 目录之上,并让其他人也可以对该目录(LibreStore-我的 WebApi 的根目录)进行写访问,然后它就工作了。

Web root has write access

我不知道为什么我必须给目录写访问,如果特定的文件已经有写访问,但这是唯一的工作。

但是一旦我做了这个更改,www-data用户就可以访问. db 文件,插入操作就成功了。

我用:

Echo exec (“ whoami”) ;

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

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

(对于寻找类似问题答案的追随者) 我在建一个 C # 。Net Core 6.0 WPF 应用程序。为了方便开发,我将 Sqlite.db3放在 c: drive 上。要写入数据库,必须以管理员身份打开 VisualStudio2019。

@ Charles 在评论中指出了这个问题的解决方案(或者至少是一个拙劣的解决方案)。这只是我把它说得更清楚了。输入 file_put_contents('./nameofyourdb.sqlite', null);(或。数据库,以你喜欢的任何一个数据库为单位)。将 php 文件放在应用程序的根目录中(或者在您希望创建 db 的任何地方) ,然后加载呈现 php 代码的页面。现在您有了一个 sqlite db,它是由运行您的 php 代码的用户创建的,这意味着您的 php 代码可以写入它。只是不要忘记在与控制台中的这个 db 交互时使用 sudo。

一个很好的干净的解决方案,这是允许您的主要用户帐户的文件写入(在我的情况下)的 http 用户,但这对我和它的简单工作。