web-dev-qa-db-fra.com

Imprimer la requête réelle exécutée par MySQLdb?

Je cherche un moyen de déboguer les requêtes lorsqu'elles sont exécutées et je me demandais s'il y avait un moyen pour que MySQLdb imprime la requête réelle qu'il exécute, une fois qu'il a fini d'insérer les paramètres et tout ça? D'après la documentation, il semble qu'il y ait un appel à Cursor.info () qui donnera des informations sur la dernière exécution de la requête, mais cela n'existe pas sur ma version (1.2.2).

Cela semble être une question évidente, mais pour toutes mes recherches, je n'ai pas pu trouver la réponse. Merci d'avance.

64
xitrium

Nous avons trouvé un attribut sur l'objet curseur appelé cursor._last_executed qui contient la dernière chaîne de requête à exécuter même lorsqu'une exception se produit. Cela a été plus facile et meilleur pour nous en production que d'utiliser le profilage tout le temps ou la journalisation des requêtes MySQL car les deux ont un impact sur les performances et impliquent plus de code ou plus de corrélation de fichiers journaux séparés, etc.

Je déteste répondre à ma propre question, mais cela fonctionne mieux pour nous.

114
xitrium

Vous pouvez imprimer la dernière requête exécutée avec l'attribut de curseur _last_executed:

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

Actuellement, il y a une discussion sur la façon d'obtenir ceci comme une fonctionnalité réelle dans pymysql (voir problème pymysql # 330: Ajouter mogrify au curseur, qui retourne la chaîne exacte à exécuter ; pymysql doit être utilisé à la place de MySQLdb)

edit: je ne l'ai pas testé maintenant, mais ce commit indique que le code suivant pourrait fonctionner:

cursor.mogrify(sql, (arg1, arg2))
27
Martin Thoma

Pour moi/pour l'instant _last_executed ne fonctionne plus. Dans la version actuelle à laquelle vous souhaitez accéder

cursor.statement.

voir: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-statement.html

15
martn_st

Une façon de le faire est d'activer profilage :

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')

les rendements

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

Notez que les arguments ont été insérés dans la requête et que la requête a été enregistrée même si la requête a échoué.

Une autre façon consiste à démarrer le serveur avec la journalisation activée:

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

Ensuite, vous devez parcourir /tmp/myquery.log pour découvrir ce que le serveur a reçu.

5
unutbu
4
picmate 涅

J'ai eu de la chance avec cursor._last_executed D'une manière générale, mais cela ne fonctionne pas correctement lorsqu'il est utilisé avec cursor.executemany(). Cela tombe tout sauf la dernière déclaration. Voici essentiellement ce que j'utilise maintenant dans cette instance à la place (basé sur des ajustements de la source de curseur MySQLDb réelle):

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    
2
BuvinJ