【问题标题】:How to detect temporary failures in MySQL?如何检测 MySQL 中的临时故障?
【发布时间】:2018-11-02 19:04:20
【问题描述】:

我正在编写一个 python 实用程序来在 MySQL 服务器上执行大量请求。如果我们检测到临时故障(例如,如果网络暂时关闭),则要求之一是重试查询(一段时间后)。我们使用MySQL Connector/Python

基本思路是:

try:
    cursor = cnx.get_cursor()
except:
    # If error is temporary, wait and retry
    # else stop
try:  
    cursor.execute(request)
except:
    # If error is temporary, wait and retry
    # else stop

游标的创建和请求分开处理,便于错误处理。

问题在于,似乎很难发现值得重试的情况。 AFAI,MySQL 错误和 MySQL 连接器/Python 中的PEP 249 errors 之间的映射不容易处理。例如,错误2013(丢失与服务器的连接)映射到InterfaceError,而错误2006(服务器已离开)映射到OperationalError,这两种情况都值得重试。

所以我想知道是否有一种常规的方式(可能基于errno)来对此类错误进行分类。

【问题讨论】:

  • 对不起,我忘记了标题中的一个重要词。
  • 您的赏金中有错字,应该是“列表”而不是“最少”。让我一时糊涂。
  • 如果使用事务,try/except 需要包含整个事务;这将解决死锁等问题。
  • @ArranCudbard-Bell 抱歉打错了。你知道怎么改吗?
  • 我想说“临时”错误的概念是特定于应用程序的,制作自定义 is_worth_retrying 函数可能是有意义的(也许,它也可以指定等待时间,视问题而定)。例如,“服务器已消失”错误肯定是 OperationalError,因为这意味着您的查询执行时间过长,超出了服务器的耐心。是否值得重试,还是应该重写查询或重新配置服务器?由您决定。

标签: mysql error-handling mysql-python


【解决方案1】:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

for i in range(0,100):
    while True:
        try:
            result = sock.connect_ex(('irc.myserver.net', 6667))
            if result == 0:
                break
            else:
                continue

您可以在进行数据传输之前或之后尝试这种事情吗?您可以检查数据库之间的连接,然后如果一切正常,您可以执行查询

【讨论】:

    【解决方案2】:

    遗憾的是,您必须编写自己的类来处理这个问题。 此代码为 alpha/beta 版本。

    有用的方法、建议或其他有用的东西。

    例如: 这个线程安全吗? 这个多类安全吗?

    用法:

    connection = mysqlc.Mysql(host='192.168.1.1', user='user', password='password', database='database')

    connection.sql(sql) 命令尽力自动处理错误。

    ---------班级------------------

    from mysql.connector import errorcode
    import mysql
    
    import mysql.connector
    
    
    
    class Mysql(object):
        __instance = None
    
        __host = None
        __user = None
        __password = None
        __database = None
    
        __session = None
        __connection = None
    
        def __new__(cls, host,user,password,database,*args, **kwargs):
            if not cls.__instance:
                cls.__instance = super(Mysql, cls).__new__(cls, *args, **kwargs)
            return cls.__instance
    
        def __init__(self, host='localhost', user='root', password='', database=''):
            self.__host = host
            self.__user = user
            self.__password = password
            self.__database = database
    
        #Open connection with database
        def _open(self):
            try:
                cnx = mysql.connector.connect(host=self.__host, user=self.__user, password=self.__password,
                                              database=self.__database)
                self.__connection = cnx
                self.__session = cnx.cursor()
            except mysql.connector.Error as err:
                if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
                    print('Something is wrong with your user name or password')
                elif err.errno == errorcode.ER_BAD_DB_ERROR:
                    print('Database does not exists')
                elif err.errno == 2003:
                    print("No connection to host")
                else:
                    print("Some other error" )
    # err 1698 access denied
                    print(err)
    
        def _close(self):
            self.__session.close()
            self.__connection.close()
    
        def sql(self, sql, *args, **kwargs):
            values = None
            arg=len(args)
            kwarg=len(kwargs)
            if self.__connection is None:
               self._open() 
            self.__connection.ping(reconnect=True,attempts=3,delay=2)
            while True:
                try:
                     if arg == 0 and kwarg ==0:
                        self.__session.execute(sql)
                     if arg == 1 and kwarg == 0:
    #                    self.__session.execute(temp)
                        self.__session.execute(sql, args[0])
    
                except InterfaceError as err:
                           self._open()
                except OprationalError as err:
                           self._open()
                except mysql.connector.Error as err:
    #                 print("err:")
    #                 print(+err.errno)
                     print("error")
                     print(format(err))
                     if err.errno == -1:
                         self._open()
    
                     if err.errno ==2003:
                         try:
                              self.__connection.ping(reconnect=True,attempts=3,delay=2)
                         except mysql.connector.Error as err:
                              print("error")
                              print(err.errno)
                              self._open()
                except:
                       print(sys.exc_info()[0])
                else:
                    self.__connection.commit()
                    break
    
    
            #row=self.__session.fetchall()
            #print(row)
    #        self.__connection.commit()
            return self.__session.lastrowid
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 2022-11-08
      • 1970-01-01
      • 2018-01-23
      • 1970-01-01
      • 2020-08-17
      相关资源
      最近更新 更多