Die aktuelle Abfrage drucken, die MySQLdb ausführt?

73

Ich suche nach einer Möglichkeit, Abfragen zu debuggen, während sie ausgeführt werden, und habe mich gefragt, ob es eine Möglichkeit gibt, MySQLdb die tatsächlich ausgeführte Abfrage ausdrucken zu lassen, nachdem die Parameter und all das vollständig eingefügt wurden. Aus der Dokumentation geht hervor, dass es einen Cursor.info () -Aufruf geben soll, der Informationen zum letzten Abfragelauf enthält, der jedoch in meiner Version (1.2.2) nicht vorhanden ist.

Dies scheint eine offensichtliche Frage zu sein, aber bei all meiner Suche konnte ich keine Antwort finden. Danke im Voraus.

Xitrium
quelle
Ich kenne diese Bibliothek nicht, aber wenn sie die vorbereiteten Anweisungen von MySQL verwendet, sieht die eigentliche Abfrage so aus EXECUTE stmt USING @var1, var2,..... Ich bin mir nicht sicher, ob es für Sie hilfreich wäre.
Mchl
Ich würde einfach das allgemeine Abfrageprotokoll einschalten und dann sehen, welche Abfrage ausgeführt wird.
Michael Mior
@MichaelMior Dies ist nicht immer eine Option, insbesondere bei gehostetem MySQL wie Amazon RDS. Es ist nützlich, pythonseitigen Zugriff darauf zu haben. (Ich wollte nur darauf hinweisen, dass es nicht immer möglich ist, die MySQL-Protokolleinstellungen zu ändern.)
Travis Leleu
@TravisLeleu Ich bin sicher, dass es einige Szenarien gibt, in denen dies zutrifft, aber Sie können auf das allgemeine Protokoll von RDS zugreifen. docs.aws.amazon.com/AmazonRDS/latest/UserGuide/…
Michael Mior

Antworten:

119

Wir haben ein Attribut für das aufgerufene  cursor._last_executedCursorobjekt gefunden, das die letzte Abfragezeichenfolge enthält, die ausgeführt wird, auch wenn eine Ausnahme auftritt. Dies war für uns in der Produktion einfacher und besser als die ständige Verwendung von Profilen oder die Protokollierung von MySQL-Abfragen, da beide Auswirkungen auf die Leistung haben und mehr Code oder mehr korrelierende separate Protokolldateien usw. beinhalten.

Ich hasse es, meine eigene Frage zu beantworten, aber das funktioniert besser für uns.

Xitrium
quelle
36

Sie können die zuletzt ausgeführte Abfrage mit dem Cursorattribut drucken _last_executed:

try:
    cursor.execute(sql, (arg1, arg2))
    connection.commit()
except:
    print(cursor._last_executed)
    raise

Derzeit wird diskutiert, wie dies als echte Funktion in pymysql verwendet werden kann (siehe pymysql-Problem Nr. 330: Fügen Sie dem Cursor mogrify hinzu, das die genaue auszuführende Zeichenfolge zurückgibt ; pymysqlsollte anstelle von verwendet werden MySQLdb).

edit: Ich habe es bis jetzt nicht getestet, aber dieses Commit zeigt an, dass der folgende Code möglicherweise funktioniert:

cursor.mogrify(sql, (arg1, arg2))
Martin Thoma
quelle
pymysql unterstützt jetzt cur.mogrify (qstr, qargs)
e1i45
6

Eine Möglichkeit besteht darin, die Profilerstellung zu aktivieren :

cursor.execute('set profiling = 1')
try:
    cursor.execute('SELECT * FROM blah where foo = %s',[11])
except Exception:
    cursor.execute('show profiles')
    for row in cursor:
        print(row)        
cursor.execute('set profiling = 0')

ergibt

(1L, 0.000154, 'SELECT * FROM blah where foo = 11')

Beachten Sie, dass die Argumente in die Abfrage eingefügt wurden und dass die Abfrage protokolliert wurde, obwohl die Abfrage fehlgeschlagen ist.

Eine andere Möglichkeit besteht darin, den Server mit aktivierter Protokollierung zu starten:

sudo invoke-rc.d mysql stop
sudo mysqld --log=/tmp/myquery.log

Dann müssen Sie /tmp/myquery.log durchsuchen, um herauszufinden, was der Server empfangen hat.

unutbu
quelle
2

Ich hatte im cursor._last_executedAllgemeinen Glück damit , aber es funktioniert nicht richtig, wenn es mit verwendet wird cursor.executemany(). Das lässt alle bis auf die letzte Aussage fallen. Hier ist im Grunde das, was ich jetzt stattdessen in dieser Instanz verwende (basierend auf Optimierungen von der tatsächlichen MySQLDb-Cursorquelle):

def toSqlResolvedList( cursor, sql, dynamicValues ):
    sqlList=[]
    try:
        db = cursor._get_db()
        if isinstance( sql, unicode ): 
            sql = sql.encode( db.character_set_name() )
        for values in dynamicValues :
            sqlList.append( sql % db.literal( values ) )
    except: pass
    return sqlList    
BuvinJ
quelle
-1

Ich kann nicht sagen, dass ich jemals gesehen habe

Cursor.info()

In der Dokumentation, und ich kann es nach ein paar Minuten Suche nicht finden. Vielleicht haben Sie eine alte Dokumentation gesehen?

In der Zwischenzeit können Sie die MySQL-Abfrageprotokollierung jederzeit aktivieren und die Protokolldateien des Servers anzeigen.

Nick Craig-Wood
quelle
Ich habe es hier gesehen mysql-python.sourceforge.net/MySQLdb.html unter "Cursor Objects": "info () Gibt einige Informationen zur letzten Abfrage zurück. Normalerweise müssen Sie dies nicht überprüfen."
Xitrium
-2

Angenommen, Ihre SQL ist wie select * from table1 where 'name' = %s

from _mysql import escape
from MySQLdb.converters import conversions

actual_query = sql % tuple((escape(item, conversions) for item in parameters))
郭润民
quelle