插入期间 SQLite 错误“尝试写入只读数据库”?
Posted
技术标签:
【中文标题】插入期间 SQLite 错误“尝试写入只读数据库”?【英文标题】:SQLite error 'attempt to write a readonly database' during insert? 【发布时间】: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
添加权限对我有用
如果您尝试访问已删除的数据库,也会显示此错误
【参考方案1】:
事实证明,问题在于 PDO SQLite 驱动程序要求如果您要执行写入操作(INSERT
、UPDATE
、DELETE
、DROP
等),那么数据库所在的文件夹必须具有写入权限,以及实际的数据库文件。
我在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。
【讨论】:
以上是关于插入期间 SQLite 错误“尝试写入只读数据库”?的主要内容,如果未能解决你的问题,请参考以下文章
Django 登录错误:在 IIS 中“尝试写入只读数据库”
BEGIN IMMEDIATE 可能在 0:8/尝试写入只读数据库后意外无法步进