5

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

这已经在 优雅地处理“MySQL 已经消失”中进行了讨论

但这并没有具体回答我的查询。

所以我处理这个问题的方法 - 我已经将我所有的 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)

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

4

3 回答 3

4

我尝试了 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

于 2015-08-06T18:02:07.643 回答
2

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

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

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

于 2013-03-08T14:07:13.270 回答
0

我遇到了令人费解的“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)))
于 2017-08-29T03:46:32.107 回答