2009-08-30 28 views
6

J'utilise Django 1.1 avec les tables Mysql 5. * et MyISAM.Django: Comment pouvez-vous empêcher les longues requêtes de détruire votre base de données?

Certaines de mes requêtes peuvent prendre beaucoup de temps pour les valeurs aberrantes dans mon ensemble de données. Ceux-ci verrouillent les tables et ferment le site. D'autres fois, il semble que certains utilisateurs annulent la requête avant que cela ne soit fait et que certaines requêtes soient bloquées dans la phase "Préparation", bloquant toutes les autres requêtes.

Je vais essayer de retrouver tous les boîtiers d'angle, mais c'est bien d'avoir un filet de sécurité pour que le site ne tombe pas.

Comment éviter cela? Puis-je définir des temps de requête maximum?

+0

Qu'est-ce qu'une valeur aberrante dans un ensemble de données? – hughdbrown

+0

Quelqu'un qui a un nombre de réalisations bien supérieur à la normale, ou un très grand nombre d'alias sur le web. –

Répondre

1

Malheureusement, MySQL ne vous permet pas d'éviter cela facilement. Une méthode courante consiste à écrire un script qui vérifie tous les processus en cours toutes les X secondes (en fonction de ce que vous pensez être "long") et d'en tuer un qui fonctionne trop longtemps. Vous pouvez au moins obtenir des diagnostics de base, en définissant log_slow_queries dans MySQL qui écrira toutes les requêtes qui durent plus de 10 secondes dans un journal. Si cela est trop long pour ce que vous considérez comme "lent" pour vos besoins, vous pouvez définir long_query_time à une valeur autre que 10 pour modifier le seuil.

+1

* soupir * j'avais peur de ça. Y a-t-il des scripts que vous recommandez pour ce travail? –

+0

avez-vous trouvé des scripts pour cela? – lamplighter

0

Il semble que le seul moyen fiable d'abandonner une requête est le kill command. Une mesure moins radicale consiste à fermer la connexion (et à en ouvrir une nouvelle); Cela met fin aux requêtes dès qu'elles tentent de send some output au client.

+1

Comment puis-je détecter cela dans django?Je préfère ne pas avoir un cronjob qui vérifie chaque seconde pour voir ce qu'il doit tuer ... –

0

Savez-vous quelles sont les requêtes? Peut-être pourriez-vous optimiser le SQL ou mettre des index sur vos tables?

+0

Bien sûr, je travaille sur les requêtes. J'ai trouvé environ 4 qui tue la DB. Mais je veux un filet de sécurité afin qu'il n'y ait pas de requête qui puisse verrouiller ma base de données et tuer le site. –

1

Je fais une application de réplication de base de données Django et j'ai la même situation, les requêtes sur un WAN peuvent parfois sembler se bloquer si la latence du réseau augmente.

De http://code.activestate.com/recipes/576780/

Recette 576780: Délai d'attente pour (presque) tout appelable

Créer un temps version limitée de toute appelable.

Par exemple, pour limiter la fonction f à t secondes, créez d'abord une version limitée dans le temps de f.

from timelimited import * 

f_t = TimeLimited(f, t) 

Ensuite, au lieu d'invoquer f(...), utilisez f_t comme

try: 
    r = f_t(...) 
except TimeLimitExpired: 
    r = ... # timed out 

Utilisez la manière suivante par exemple:

def _run_timed_query(cursor, log_msg, timeout, query_string, *query_args): 
    """Run a timed query, do error handling and logging""" 
    import sys 
    import traceback 
    from timelimited import * 

    try: 
     return TimeLimited(cursor.execute, timeout)(query_string, *query_args) 
    except TimeLimitExpired: 
     logger_ec.error('%s; Timeout error.' % log_msg) 
     raise TimeLimitExpired 
    except: 
     (exc_type, exc_info, tb) = sys.exc_info() 
     logger_ec.error('%s; %s.' % (log_msg, traceback.format_exception(exc_type, exc_info, None)[0])) 
     raise exc_type 
0

Utilisez les tables InnoDB, ils row-locking au lieu de table-locking.

+0

Je l'ai fait, mais je lis surtout, et InnoDB était un ralentissement de l'ordre de grandeur pour ma requête de charge :( –

0

Vous ne devriez pas écrire des requêtes de ce type, au moins de ne pas exécuter votre base de données en direct. Mysql a un paramètre "lent requêtes" que vous pouvez utiliser pour identifier les requêtes qui vous tuent. La plupart du temps, ces requêtes lentes sont buggées ou peuvent être accélérées en définissant un nouvel index ou deux.

Questions connexes