2010-01-01 8 views
17

Ich schreibe einen kleinen Datenbankadapter in Python, meistens zum Spaß. Ich versuche, den Code aus einer Situation wiederherzustellen, in der die MySQL-Verbindung "weggeht", aka wait_timeout, überschritten wird. Ich habe wait_timeout um 10 gesetzt, also kann ich das versuchen.Gracefully Behandlung "MySQL ist weggegangen"

Hier ist mein Code:

def select(self, query, params=[]): 
     try: 
      self.cursor = self.cxn.cursor() 
      self.cursor.execute(query, params) 
     except MySQLdb.OperationalError, e: 
      if e[0] == 2006: 
       print "We caught the exception properly!" 
       print self.cxn 
       self.cxn.close() 
       self.cxn = self.db._get_cxn() 
       self.cursor = self.cxn.cursor() 
       self.cursor.execute(query, params) 
       print self.cxn 

     return self.cursor.fetchall() 

Next ich zehn Sekunden warten und versuchen, einen Antrag zu stellen. So sieht CherryPy aus:

[31/Dec/2009:20:47:29] ENGINE Bus STARTING 
[31/Dec/2009:20:47:29] ENGINE Starting database pool... 
[31/Dec/2009:20:47:29] ENGINE POOL Connecting to MySQL... 
[31/Dec/2009:20:47:29] ENGINE POOL Connecting to MySQL... 
[31/Dec/2009:20:47:29] ENGINE POOL Connecting to MySQL... 
[31/Dec/2009:20:47:29] ENGINE POOL Connecting to MySQL... 
[31/Dec/2009:20:47:29] ENGINE POOL Connecting to MySQL... 
[31/Dec/2009:20:47:29] ENGINE Started monitor thread '_TimeoutMonitor'. 
[31/Dec/2009:20:47:29] ENGINE Started monitor thread 'Autoreloader'. 
[31/Dec/2009:20:47:30] ENGINE Serving on 0.0.0.0:8888 
[31/Dec/2009:20:47:30] ENGINE Bus STARTED 
We caught the exception properly! <====================================== Aaarg! 
<_mysql.connection open to 'localhost' at 1ee22b0> 
[31/Dec/2009:20:48:25] HTTP Traceback (most recent call last): 
    File "/usr/local/lib/python2.6/dist-packages/CherryPy-3.1.2-py2.6.egg/cherrypy/_cprequest.py", line 606, in respond 
cherrypy.response.body = self.handler() 
    File "/usr/local/lib/python2.6/dist-packages/CherryPy-3.1.2-py2.6.egg/cherrypy/_cpdispatch.py", line 25, in __call__ 
    return self.callable(*self.args, **self.kwargs) 
    File "adp.py", line 69, in reports 
    page.sources = sql.GetSources() 
    File "/home/swoods/dev/adp/sql.py", line 45, in __call__ 
    return getattr(self.formatter.cxn, parsefn)(sql, sql_vars) 
    File "/home/swoods/dev/adp/database.py", line 96, in select 
    self.cursor.execute(query, params) 
    File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 166, in execute 
    self.errorhandler(self, exc, value) 
    File "/usr/lib/pymodules/python2.6/MySQLdb/connections.py", line 35, in defaulterrorhandler 
    raise errorclass, errorvalue 
OperationalError: (2006, 'MySQL server has gone away') 

[31/Dec/2009:20:48:25] HTTP 
Request Headers: 
    COOKIE: session_id=e14f63acc306b26f14d966e606612642af2dd423 
    HOST: localhost:8888 
    CACHE-CONTROL: max-age=0 
    ACCEPT: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 
    ACCEPT-CHARSET: ISO-8859-1,utf-8;q=0.7,*;q=0.3 
    USER-AGENT: Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.5 (KHTML, like  Gecko) Chrome/4.0.249.43 Safari/532.5 
    CONNECTION: keep-alive 
    Remote-Addr: 127.0.0.1 
    ACCEPT-LANGUAGE: en-US,en;q=0.8 
    ACCEPT-ENCODING: gzip,deflate 
127.0.0.1 - - [31/Dec/2009:20:48:25] "GET /reports/1 HTTP/1.1" 500 1770 "" "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.43 Safari/532.5" 

Warum funktioniert das nicht? Ich erhalte eindeutig die Ausnahme, regeneriere sowohl die Verbindung als auch den Cursor, aber es funktioniert immer noch nicht. Ist es verwandt damit, wie MySQLdb die Verbindungen bekommt?

Antwort

12

Kann nicht aus dem Code sehen, aber meine Vermutung wäre, dass die db._get_cxn() Methode eine Art Verbindungspooling und das vorhandene Verbindungsobjekt zurückgibt, anstatt ein neues zu erstellen. Gibt es keinen Anruf, den Sie unter db tätigen können, um die bestehende nutzlose Verbindung zu löschen? (Und sollten Sie wirklich eine interne _ -vorgesetzte Methode aufrufen?)

Zum Verhindern MySQL has gone away Ich bevorzuge im Allgemeinen einen Zeitstempel mit der Verbindung der letzten Zeit, die ich es verwendete. Dann, bevor ich versuche, es wieder zu benutzen, schaue ich auf den Zeitstempel und schließe/verwerfe die Verbindung, wenn sie vor mehr als ein paar Stunden zuletzt benutzt wurde. Dies spart das Umbrechen aller möglichen Abfragen mit einer try...except OperationalError...try again.

+0

Richtig Sie sind auf beiden Konten. Dieses Ding ist in viele verschiedene Richtungen gegangen. Ich habe den Vorschlag aus Absatz 2 tatsächlich umgesetzt und es ist meine bevorzugte Vorgehensweise. Ich habe den Code umgeschrieben, um den Fehler zu beheben, den Sie in Absatz 1 vorgeschlagen haben (der Fehler war genau das ... Ich bin ein Opfer meines eigenen Refactorings). Vielen Dank für Ihre Hilfe. Frohes neues Jahr! –

+5

@SeanWoods - Können Sie Ihren korrigierten Code teilen? Ich habe das gleiche Problem wie du ... – Jonathan

+0

@SeanWoods Hast du irgendwelche Gedanken über die Freigabe des Codes gegeben? Sieht aus, als ob ich auch unter dem gleichen Fehler leide. Ich habe eine While-Schleife um meine erste Datenbankverbindung für 3 Versuche gelegt, aber wie Bobince erwähnte, habe ich versucht, außer in jeder einzelnen Abfrage. Ich habe es versucht, außer für jede einzelne Abfrage, aber ich bin nicht wirklich abfangen Server Ausnahme. –

Verwandte Themen