【问题标题】:Python: MySQL: Handling timeoutsPython:MySQL:处理超时
【发布时间】:2012-11-26 16:01:26
【问题描述】:

我正在使用 Python 和 mySQL,查询之间有很长的延迟。结果,我收到“MySQL 连接已消失”错误,即已超出 wait_timeout。

这已经被讨论过,例如在 Gracefully handling "MySQL has gone away"

但这并没有具体回答我的问题。

所以我的处理方法 - 我已经将我所有的 sql 执行语句包装在一个方法中 -

  def __execute_sql(self,sql,cursor):
    try:
        cursor.execute(sql)

    except MySQLdb.OperationalError, e:            
        if e[0] == 2006:
            self.logger.do_logging('info','DB', "%s : Restarting db" %(e))
            self.start_database()

我在代码中有几个地方调用了这个查询。问题是,我也有几个游标,所以方法调用看起来像-

self.__execute_sql(sql,self.cursor_a)
self.__execute_sql(sql,self.cursor_b)

等等

我需要一种在数据库启动后优雅地重新执行查询的方法。我可以将调用包装在 if 语句中,然后重新执行,这样就可以了

def __execute_sql(self,sql,cursor):
    try:
        cursor.execute(sql)
        return 1
except MySQLdb.OperationalError, e:            
    if e[0] == 2006:
        self.logger.do_logging('info','DB', "%s : Restarting db" %(e))
        self.start_database()
        return 0

然后

if (self.__execute_sql(sql,self.cursor_a) == 0):
   self.__execute_sql(sql,self.cursor_a)

但这很笨拙。有一个更好的方法吗? 谢谢!!!

【问题讨论】:

    标签: python mysql timeout


    【解决方案1】:

    我尝试了 Crasched 的方法,这让我遇到了一个新的 OperationalError:

    OperationalError: (2013, 'Lost connection to MySQL server during query')

    我的最终解决方案是首先尝试 ping,如果引发另一个 OperationalError,则使用新连接重新连接并重新创建光标,如下所示:

    try:
        self.connection.ping(True)
    except MySQLdb.OperationalError:
        self.connection = MySQLdb.connect(
            self.db_host,
            self.db_user,
            self.db_passwd,
            self.db_dbase,
            self.db_port)
        # reconnect your cursor as you did in __init__ or wherever    
        self.cursor = self.connection(
            MySQLdb.cursors.DictCursor)
    

    恢复营业!

    Python 2.7、MySQL 5.5.41

    【讨论】:

    • 在运行查询之前 Ping 被认为是一种浪费资源且不可靠的反模式:percona.com/blog/2010/05/05/…
    • @kiminoa - 尝试执行查询,并捕获任何 MySQL 错误,在这种情况下您重新尝试查询。
    【解决方案2】:

    我遇到了同样的问题,想包装异常来捕获它,但我使用以下方法解决了它。 在调用执行之前,调用
    self.con.ping(TRUE)

    http://www.neotitans.com/resources/python/mysql-python-connection-error-2006.html http://mysql-python.sourceforge.net/MySQLdb.html

    我无法再找到我从中找到的原始源材料,但这立即解决了问题。

    【讨论】:

    【解决方案3】:

    我遇到了令人费解的“MySQL 服务器已消失”错误,这是我的解决方案。

    此解决方案可让您重试 MySQL 错误,处理几乎任何类型的查询,在查询 str 或单独的元组中包含查询变量,并收集并返回您在此过程中遇到的所有成功和错误消息:

    def execute_query(query_str, values=None):
      # defaults
      num_affected_rows = 0
      result_rows = None
      success = False
      message = "Error executing query: {}".format(query_str)
      # run the query
      try:
        mysql_conn = get_existing_mysql_connection()
        cur = mysql_conn.cursor()
        if values == None or len(values) < 1:
          num_affected_rows = cur.execute(query_str)
        else:
          num_affected_rows = cur.execute(query_str, values)
        result_rows = cur.fetchall() # only relevant to select, but safe to run with others
        cur.close()
        mysql_conn.commit()
        success = True
        message = "Mysql success for query: {}".format(query_str)
      except BaseException as e:
        message = "Mysql error: {}; for query: {}".format(repr(e), query_str)
      return (success, num_affected_rows, result_rows, message)
    
    
    def execute_query_with_retry(query_str, values=None, num_tries=3, message=""):
      # defaults
      success = False
      num_affected_rows = 0
      result_rows = None
      this_message = "Error executing query: {}".format(query_str)
      # should we still try?
      if num_tries < 1:
        this_message = "Ran out of tries for query: {}".format(query_str)
        return (False, 0, None, message + '; ' + this_message)
      num_tries_after_this = num_tries - 1
      # try to execute query
      try:
        (success, num_affected_rows, result_rows, this_message) = execute_query(query_str, values)
      except BaseException as e:
        success = False
      # handle success or failure
      if success == True:
        return (True, num_affected_rows, result_rows, message + '; ' + this_message)
      else:
        open_new_mysql_connection() # reconnect using password etc.
        return(execute_query_with_retry(query_str, values=values, num_tries=num_tries_after_this, message=(message + '; ' + this_message)))
    

    【讨论】:

      猜你喜欢
      • 2018-07-29
      • 2021-03-01
      • 2023-03-24
      • 2016-11-22
      • 2015-01-28
      • 2012-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多