【问题标题】:Print the actual query MySQLdb runs?打印 MySQLdb 运行的实际查询?
【发布时间】:2011-10-27 14:55:54
【问题描述】:

我正在寻找一种在执行查询时调试查询的方法,我想知道是否有一种方法可以让 MySQLdb 在完成插入参数之后打印出它运行的实际查询?从文档来看,似乎应该有一个 Cursor.info() 调用,它将提供有关上次查询运行的信息,但这在我的版本 (1.2.2) 上不存在。

这似乎是一个显而易见的问题,但我一直在寻找答案。提前致谢。

【问题讨论】:

  • 不知道这个库,但如果它使用实际 MySQL 的准备语句,那么实际查询将类似于 EXECUTE stmt USING @var1, var2,....。不知道对你有没有帮助。
  • 我只需打开general query log,然后查看执行了什么查询。
  • @MichaelMior 这并不总是一种选择,尤其是对于像 Amazon 的 RDS 这样的托管 MySQL。让 python 端访问它很有用。 (只是想指出,改变mysql日志设置并不总是可行的。)
  • @TravisLeleu 我确信在某些情况下确实如此,但您可以访问 RDS 上的常规日志。 docs.aws.amazon.com/AmazonRDS/latest/UserGuide/…

标签: python mysql mysql-python


【解决方案1】:

我不能说我见过

Cursor.info()

在文档中,我在搜索了几分钟后找不到它。也许您看到了一些旧文档?

与此同时,您可以随时打开MySQL Query Logging 并查看服务器的日志文件。

【讨论】:

【解决方案2】:

一种方法是打开profiling

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

产量

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

注意参数被插入到查询中,即使查询失败,查询也会被记录。

另一种方法是在打开日志的情况下启动服务器:

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

然后您必须筛选 /tmp/myquery.log 以找出服务器收到的内容。

【讨论】:

    【解决方案3】:

    我们在名为cursor._last_executed 的游标对象上发现了一个属性,该属性包含最后一个要运行的查询字符串,即使发生异常也是如此。这对我们来说在生产环境中比一直使用分析或 MySQL 查询日志更容易和更好,因为这两者都会影响性能并且涉及更多代码或更多相关的单独日志文件等。

    讨厌回答我自己的问题,但这对我们来说效果更好。

    【讨论】:

      【解决方案4】:

      您可以使用光标属性_last_executed打印最后执行的查询:

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

      目前,有一个讨论如何在 pymysql 中将其作为一个真正的功能(参见pymysql issue #330: Add mogrify to Cursor, which returns the exact string to be executed;应该使用pymysql 而不是MySQLdb

      编辑:我现在还没有测试它,但this commit 表明以下代码可能有效:

      cursor.mogrify(sql, (arg1, arg2))
      

      【讨论】:

      • pymysql 现在支持 cur.mogrify(qstr, qargs)
      【解决方案5】:

      对我/现在_last_executed 不再起作用了。在你要访问的当前版本中

      cursor.statement

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

      【讨论】:

      • 是 - 'CMySQLCursor' 对象没有属性 '_last_executed'
      • 如果您的查询引发异常,这将失败
      【解决方案6】:

      假设你的sql类似于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))
      

      【讨论】:

        【解决方案7】:
        【解决方案8】:

        一般来说,我对cursor._last_executed 很幸运,但是在与cursor.executemany() 一起使用时它不能正常工作。除了最后一个陈述之外,这一切都消失了。这基本上是我现在在该实例中使用的(基于实际 MySQLDb 游标源的调整):

        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    
        

        【讨论】:

          【解决方案9】:

          cursor.statementcursor._last_executed 引发 AttributeError 异常

          cursor._executed
          

          为我工作!

          【讨论】:

            【解决方案10】:

            此只读属性以字符串形式返回最后执行的语句。 statement 属性可用于调试和显示发送到 MySQL 服务器的内容。 如果执行了多语句字符串,则该字符串可以包含多个语句。这发生在 multi=True 的 execute() 上。在这种情况下,statement 属性包含整个语句字符串,并且 execute() 调用返回一个迭代器,该迭代器可用于处理各个语句的结果。此迭代器的语句属性显示各个语句的语句字符串。

            str = cursor.statement

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

            【讨论】:

              猜你喜欢
              • 2011-08-03
              • 2011-02-11
              • 2017-06-17
              • 2017-05-01
              • 1970-01-01
              • 1970-01-01
              • 2011-10-15
              相关资源
              最近更新 更多