38 votes

SQLite3 :: BusyException

L'exécution d'un des rails site dès maintenant à l'aide de SQLite3.

Environ une fois tous les 500 demandes ou alors, je reçois un

ActiveRecord::StatementInvalid (SQLite3::BusyException: base de données est verrouillée:...

Quel est le moyen de corriger ce qui serait minimalement invasive à mon code?

Je suis l'aide de SQLLite pour le moment parce que vous pouvez stocker les données dans la source de contrôle qui rend la sauvegarde de naturel et vous pouvez le pousser à des changements très rapidement. Cependant, il n'est évidemment pas vraiment mis en place pour l'accès simultané. Je vais migrer vers MySQL demain matin.

57voto

Rifkin Habsburg Points 461

Vous avez mentionné qu'il s'agissait d'un site Rails. Rails vous permet de définir le délai d'attente avant nouvelle tentative SQLite dans votre fichier de configuration database.yml:

 production:
  adapter: sqlite3
  database: db/mysite_prod.sqlite3
  timeout: 10000
 

La valeur de délai d'attente est spécifiée en millisecondes. L'augmenter à 10 ou 15 secondes devrait réduire le nombre d'exceptions BusyExceptions que vous voyez dans votre journal.

Ce n'est cependant qu'une solution temporaire. Si votre site nécessite une concurrence réelle, vous devrez migrer vers un autre moteur de base de données.

9voto

ravenspoint Points 8840

Par défaut, sqlite renvoie immédiatement avec une erreur bloquée, si la base de données est occupée et verrouillée. Vous pouvez lui demander d'attendre et de continuer à essayer pendant un moment avant d'abandonner. Cela résout généralement le problème, sauf si vous avez 1 000 threads accédant à votre base de données, lorsque je conviens que SQLite serait inapproprié.

    // définit SQLite pour attendre et réessayer jusqu'à 100 ms si la base de données est verrouillée
    sqlite3_busy_timeout (db, 100);

3voto

ybakos Points 1829

Toutes ces choses sont vraies, mais cela ne répond pas à la question probablement suivante: pourquoi mon application Rails soulève-t-elle parfois une exception SQLite3 :: BusyException en production?

@Shalmanese: à quoi ressemble l'environnement d'hébergement de production? Est-ce sur un hôte partagé? Le répertoire contenant la base de données sqlite est-il sur un partage NFS? (Probablement sur un hôte partagé).

Ce problème est probablement dû au phénomène de verrouillage de fichiers avec des partages NFS et au manque de simultanéité de SQLite.

2voto

Ignacio Huerta Points 106

Juste pour le record. Dans une application avec des Rails 2.3.8 nous avons constaté que les Rails ne tienne pas compte de l'option "timeout" Rifkin Habsbourg suggéré.

Après quelques enquête, nous avons constaté un éventuel problème dans les Rails dev: http://dev.rubyonrails.org/ticket/8811. Et après plus d'enquête, nous avons trouvé la solution (testé avec des Rails 2.3.8):

Modifier ce ActiveRecord fichier: activerecord-2.3.8/lib/active_record/connection_adapters/sqlite_adapter.rb

Remplacer ce:

  def begin_db_transaction #:nodoc:
    catch_schema_changes { @connection.transaction }
  end

avec

  def begin_db_transaction #:nodoc:
    catch_schema_changes { @connection.transaction(:immediate) }
  end

Et c'est tout! Nous n'avons pas remarqué une chute des performances et maintenant, l'application supporte beaucoup plus de pétitions sans rupture (il attend la fin de la temporisation). Sqlite est sympa!

0voto

Brian R. Bondy Points 141769

Source: ce lien

 - Open the database
db = sqlite3.open("filename")

-- Ten attempts are made to proceed, if the database is locked
function my_busy_handler(attempts_made)
  if attempts_made < 10 then
    return true
  else
    return false
  end
end

-- Set the new busy handler
db:set_busy_handler(my_busy_handler)

-- Use the database
db:exec(...)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X