【问题标题】:SQLite error 'attempt to write a readonly database' during insert?插入期间 SQLite 错误“尝试写入只读数据库”?
【发布时间】:2011-03-20 03:31:19
【问题描述】:

我有一个用于网站的 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) 不是你,所以它不拥有文件,所以它没有写权限...有趣...
  • sudo chgrp www-data test.db 添加权限对我有用
  • 如果您尝试访问已删除的数据库,也会显示此错误

标签: sqlite permissions


【解决方案1】:

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

我在comment at the very bottom of the PDO SQLite driver manual page 中找到了此信息。

【讨论】:

  • 此外,SELinux(如果已安装)不得强制执行。我花了一天半的时间才弄明白。
  • 嗯,对不起,但我感谢它,但它只是暂时解决了问题,主要问题是我的 www-data 用户不在 www-data 组中。
  • 据我所知,包含文件夹必须是可写的,因为在写入日志文件时将创建数据库本身。要拥有与网络服务器相同的用户,请尝试将文件的内容复制到另一个创建的 ad hoc。
  • 另外,db 文件及其所在的目录必须由 linux 机器上的“www-data”拥有。
  • 目前 sqlite3 可能有 3 个文件,.db,一个.db-shm 和一个.db-wal 文件,当然还有这三个文件的父目录,对于运行的用户必须都是可写的程序。
【解决方案2】:

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

谁拥有 SQLite 文件?你呢?

脚本以谁的身份运行?阿帕奇还是没人?

【讨论】:

  • 我拥有 SQLite 文件,但我不知道脚本以谁的身份运行。我怎样才能知道? (请记住,这是在共享主机上,我的权限有限)
  • 啊,这让事情变得更有趣了。如果您使用的是共享主机,则脚本很有可能以“nobody”或“apache”的身份运行。让您的脚本创建一个文件 (file_put_contents('./foo.txt', 'Hello, world');),该文件将向您显示它以谁的身份运行。您可能需要让脚本创建 SQLite 数据库。如果您的当前文件中已经有数据,这可能是一个有趣的练习...
  • 好主意,但不行。运行 PHP 的人没有写入权限,因此无法创建文件。无论如何PHP可以检索它当前运行的用户吗?
  • 唯一的方法似乎是through the POSIX extension,它在 POSIX-y 系统上默认启用。不过,您的托管服务提供商可能有 R'd TFM 并禁用了它。
  • 好吧,他们研发了 TFM,好吧。 posix_getuid() 也不起作用。
【解决方案3】:

对我来说,问题是SELinux enforcement 而不是权限。根据 Steve V. 在 the accepted answer.

的评论中提出的建议,一旦我禁用强制执行,“只读数据库”错误就会消失
echo 0 >/selinux/enforce

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

我遇到的具体问题是在设置 Graphite 期间。我已经三重检查了 apache 用户是否拥有并且可以写入我的石墨.db 及其父目录。但是在我“修复” SELinux 之前,我得到的只是一个堆栈跟踪,其效果是:DatabaseError: attempt to write a readonly database

【讨论】:

  • SELinux 是一种安全措施,因此不应在没有充分理由的情况下禁用。最好首先弄清楚 SELinux 阻塞的原因并正确配置它而不是禁用它。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    当我尝试在 Android 系统上写入数据库时​​遇到此错误。

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

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

    编辑:

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

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

          【解决方案8】:

          我用过:

          echo exec('whoami');

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

          sudo chown -R :username /var/www/html/myapp

          【讨论】:

            【解决方案9】:

            当我从使用 http://localhost 更改为 http://145.900.50.20(其中 145.900.50.20 是我的本地 IP 地址)然后又改回 localhost 时,我在浏览器中得到了这个 - 有必要保留一次 IP 地址我曾经改变过一次

            【讨论】:

              【解决方案10】:

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

              【讨论】:

                猜你喜欢
                • 2015-10-27
                • 2021-09-11
                • 2017-07-17
                • 2021-05-01
                • 2016-10-20
                • 2017-09-27
                • 2018-05-23
                • 2020-11-21
                相关资源
                最近更新 更多