web-dev-qa-db-fra.com

SQLite: base de données en lecture seule

J'ai une base de données SQLite que j'utilise pour un site web. Le problème est que lorsque j'essaie de INSERT INTO, je reçois une PDOException

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

J'ai SSH dans le serveur et vérifié les autorisations, et la base de données a les autorisations

-rw-rw-r--

Je ne connais pas très bien les permissions * nix, mais je suis sûr que cela signifie

  • Pas un annuaire
  • Le propriétaire a des autorisations de lecture/écriture (c'est moi, selon ls -l)
  • Le groupe a des autorisations de lecture/écriture
  • Tout le monde n'a que des autorisations de lecture

J'ai également cherché partout où je savais utiliser le programme sqlite3 et je n'ai rien trouvé de pertinent.

Parce que je ne savais pas avec quelles autorisations PDO essayait d'ouvrir la base de données, j'ai

chmod o+w supplies.db

Maintenant, je reçois une autre PDOException:

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

Mais cela se produit UNIQUEMENT lorsque j'essaie d'exécuter une requête INSERTaprès que la base de données est ouverte.

Des idées sur ce qui se passe?

102
Austin Hyde

Le problème, comme il s’est avéré, est que le pilote PDO SQLite exige que, si vous voulez effectuer une opération d’écriture (INSERT, UPDATE, DELETE, DROP, etc.), le dossier dans lequel se trouve la base de données doit disposer des autorisations en écriture. ainsi que le fichier de base de données réelle.

J'ai trouvé cette information dans un commentaire tout en bas de la page de manuel du pilote PDO SQLite .

273
Austin Hyde

Cela peut se produire lorsque le propriétaire du fichier SQLite lui-même est pas identique à l'utilisateur qui exécute le script. Des erreurs similaires peuvent se produire si le chemin d'accès au répertoire complet (c'est-à-dire chaque répertoire au cours du chemin) ne peut pas être écrit. 

À qui appartient le fichier SQLite? Vous?

Qui est le script en cours d'exécution? Apache ou personne?

12
Charles

Pour moi, le problème était l’application SELinux plutôt que les autorisations. L'erreur "lecture seule" a disparu une fois que j'ai désactivé l'application, à la suite de la suggestion de Steve V. dans un commentaire sur la réponse acceptée.

echo 0 >/selinux/enforce

Lors de l'exécution de cette commande, tout a fonctionné comme prévu (CentOS 6.3).

Le problème spécifique que j'avais rencontré était lors de l'installation de Graphite. J'avais vérifié à trois reprises que l'utilisateur Apache possédait et pouvait écrire à la fois dans mon graphite.db et son répertoire parent. Mais jusqu'à ce que je "corrige" SELinux, tout ce que j'ai obtenu est une trace de pile sous l'effet de: DatabaseError: tentative d'écriture d'une base de données en lecture seule

5
Noah Sussman

Cela peut être causé par SELinux. Si vous ne souhaitez pas désactiver complètement SELinux, vous devez définir le répertoire de base de données fcontext sur httpd_sys_rw_content_t.

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

J'ai reçu la même erreur de IIS sous Windows 7. Pour corriger cette erreur, je devais ajouter des autorisations de contrôle total au compte IUSR du fichier de base de données sqlite. Vous n'avez pas besoin de modifier les autorisations si vous utilisez sqlite sous WebMatrix au lieu de IIS.

1
l0pan

En résumé, j'ai résolu le problème en plaçant le fichier de base de données (* .db) dans un sous-dossier.

  • Le sous-dossier et le fichier de base de données qu'il contient doivent être membres du groupe www-data.
  • Dans le groupe www-data, vous devez avoir le droit d'écrire dans le sous-dossier et le fichier de base de données.
0
Erkan Hürnalı

J'ai eu cette erreur quand j'ai essayé d'écrire dans une base de données sur un système Android.

Apparemment, sqlite3 n'a pas seulement besoin d'autorisations d'écriture sur le fichier de base de données et le répertoire contenant (comme @ austin-hyde l'a déjà indiqué dans sa réponse), mais également la variable d'environnement TMPDIR doit pointer vers un répertoire (éventuellement inscriptible).

Sur mon système Android, je le règle sur TMPDIR="/data/local/tmp" et maintenant mon script s'exécute comme prévu :)

0
Thilo