如何检测 MySQL 中的临时故障?
Posted
技术标签:
【中文标题】如何检测 MySQL 中的临时故障?【英文标题】:How to detect temporary failures in 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,因为这意味着您的查询执行时间过长,超出了服务器的耐心。是否值得重试,还是应该重写查询或重新配置服务器?由您决定。
【参考方案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
【讨论】:
以上是关于如何检测 MySQL 中的临时故障?的主要内容,如果未能解决你的问题,请参考以下文章
mysql语句的简化:from中的临时表作为where中的条件