2014-07-25 6 views
14

J'ai une application sqlalchemy qui retourne TimeOut:Sql Alchemy QueuePool dépassement de la limitation

TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 30

Je lis dans un autre poste que ce qui se passe quand je ne suis pas fermer la session, mais je ne sais pas si cela s'applique à mon code:

je me connecte à la base de données dans le init.py:

from .dbmodels import (
    DBSession, 
    Base,  

engine = create_engine("mysql://" + loadConfigVar("user") + ":" + loadConfigVar("password") + "@" + loadConfigVar("host") + "/" + loadConfigVar("schema")) 

     #Sets the engine to the session and the Base model class 
     DBSession.configure(bind=engine) 
     Base.metadata.bind = engine 

Puis dans un autre fichier python Je collecte des données dans deux fonctions, mais en utilisant DBSession que j'initialisés en init.py:

from .dbmodels import DBSession 
from .dbmodels import resourcestatsModel 

def getFeaturedGroups(max = 1): 

      try: 
       #Get the number of download per resource 
       transaction.commit() 
       rescount = DBSession.connection().execute("select resource_id,count(resource_id) as total FROM resourcestats") 

       #Move the data to an array 
       resources = [] 
       data = {} 
       for row in rescount: 
        data["resource_id"] = row.resource_id 
        data["total"] = row.total 
        resources.append(data) 

       #Get the list of groups 
       group_list = toolkit.get_action('group_list')({}, {}) 
       for group in group_list: 
        #Get the details of each group 
        group_info = toolkit.get_action('group_show')({}, {'id': group}) 
        #Count the features of the group 
        addFesturedCount(resources,group,group_info) 

       #Order the FeaturedGroups by total 
       FeaturedGroups.sort(key=lambda x: x["total"],reverse=True) 

       print FeaturedGroups 
       #Move the data of the group to the result array. 
       result = [] 
       count = 0 
       for group in FeaturedGroups: 
        group_info = toolkit.get_action('group_show')({}, {'id': group["group_id"]}) 
        result.append(group_info) 
        count = count +1 
        if count == max: 
         break 

       return result 
      except: 
       return [] 

    def getResourceStats(resourceID): 
     transaction.commit() 
     return DBSession.query(resourcestatsModel).filter_by(resource_id = resourceID).count() 

Les variables de session sont créés comme ceci:

#Basic SQLAlchemy types 
from sqlalchemy import (
    Column, 
    Text, 
    DateTime, 
    Integer, 
    ForeignKey 
    ) 
# Use SQLAlchemy declarative type 
from sqlalchemy.ext.declarative import declarative_base 

# 
from sqlalchemy.orm import (
    scoped_session, 
    sessionmaker, 
    ) 

#Use Zope' sqlalchemy transaction manager 
from zope.sqlalchemy import ZopeTransactionExtension 

#Main plugin session 
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) 

la session est créé dans le init.py et dans le code après que je viens de l'utiliser; À quel moment dois-je fermer la session? Ou quoi d'autre dois-je faire pour gérer la taille du pool?

+0

Dans le second extrait de code, où i s 'transaction' est-il défini? –

+0

Où 'getResourceStats' est-il utilisé? Il semble que la moitié du code est manquant - pouvez-vous ajouter tout cela ou il peut être impossible de diagnostiquer le problème. –

+1

Ce code fonctionne-t-il tel quel? L'instruction 'import' semble vraiment étrange, en plus des problèmes mentionnés par @TomDalton. À quel moment l'erreur se produit-elle? Est-ce l'exemple [Minimal, Complete, Verifiable] (http://stackoverflow.com/help/mcve)? IOW, pouvez-vous réduire cela (ou significativement) et toujours présenter le même comportement? Il semble y avoir beaucoup de logique commerciale là-bas qui est très peu probable la cause du problème. Essayez de le supprimer et de publier un exemple de travail complet (syntaxiquement correct), et je serais ravi de vous aider. – cod3monk3y

Répondre

15

Vous pouvez gérer la taille de la piscine en ajoutant des paramètres pool_size et max_overflow en fonction create_engine

engine = create_engine("mysql://" + loadConfigVar("user") + ":" + loadConfigVar("password") + "@" + loadConfigVar("host") + "/" + loadConfigVar("schema"), 
         pool_size=20, max_overflow=0) 

Référence est here

Vous n'avez pas besoin de fermer la session, mais la connexion doit être fermé après votre la transaction a été effectuée. Remplacer:

rescount = DBSession.connection().execute("select resource_id,count(resource_id) as total FROM resourcestats") 

Par:

connection = DBSession.connection() 
try: 
    rescount = connection.execute("select resource_id,count(resource_id) as total FROM resourcestats") 
    #do something 
finally: 
    connection.close() 

Référence est here

Notez également que la connexion de MySQL, qui rassis est fermé après une période de temps (cette période peut être configurée en MySQL, je ne me souviens pas de la valeur par défaut), vous devez donc passer la valeur pool_recycle à la création de votre moteur

Questions connexes