Every time I'm restarting mysql
service, my app is receiving the following error on any query:
result = self._query(query)
File "/usr/local/lib/python3.6/site-packages/pymysql/cursors.py", line 328, in _query
conn.query(q)
File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 516, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 727, in _read_query_result
result.read()
File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 1066, in read
first_packet = self.connection._read_packet()
File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 656, in _read_packet
packet_header = self._read_bytes(4)
File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 702, in _read_bytes
CR.CR_SERVER_LOST, "Lost connection to MySQL server during query")
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') [SQL: ...] [parameters: {...}] (Background on this error at: http://sqlalche.me/e/e3q8)
Any query after that will succeed as usual.
This is just a common use case for example, in general I might want to retry any query depending on the error.
Is there any way to catch and retry the query in some low level sqlalchemy
api? Doing try-except or a custom query
method in my code is not reasonable as I use it too many times and its not maintainable.
Apparently sqlalchemy
has a great option to customize the query class, which was exactly what I needed.
class implementation:
import logging
from flask_sqlalchemy import BaseQuery
from sqlalchemy.exc import OperationalError
from time import sleep
class RetryingQuery(BaseQuery):
__retry_count__ = 3
__retry_sleep_interval_sec__ = 0.5
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def __iter__(self):
attempts = 0
while True:
attempts += 1
try:
return super().__iter__()
except OperationalError as ex:
if "Lost connection to MySQL server during query" not in str(ex):
raise
if attempts < self.__retry_count__:
logging.debug(
"MySQL connection lost - sleeping for %.2f sec and will retry (attempt #%d)",
self.__retry_sleep_interval_sec__, attempts
)
sleep(self.__retry_sleep_interval_sec__)
continue
else:
raise
usage:
class BaseModel(Model):
...
query_class = RetryingQuery
...
db = SQLAlchemy(model_class=BaseModel, query_class=RetryingQuery)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With