Как освободить результирующий набор коннектора mysql в случае исключения - PullRequest
0 голосов
/ 29 января 2020

У меня есть приложение flask, которое запрашивает базу данных и возвращает около 250 тыс. Строк, преобразует их в формат JSON и передает результат клиенту. Я использую python генераторы для достижения потоковой передачи. Это выглядит примерно следующим образом:

@contextlib.contextmanager
def getKeyConnection():
    with keypoolsem:
        cnx = keycnxpool.get_connection()
        try:
            yield cnx
        finally:
            cnx.close()

@contextlib.contextmanager
def getKeyConnectionCursor():
    with getKeyConnection() as db:
        cursor = db.cursor(dictionary=True)
        try:
            yield cursor
        finally:
            cursor.close()

def segmentsInComputationGenerator(computation):
    with getKeyConnectionCursor() as cursor:
        cursor.execute(/*params*/)
        results = cursor.fetchmany(fetchWidth)
        yield '['
        while results:
            output = ""
            //transform data to json
            results = cursor.fetchmany(fetchWidth)
            yield output
        yield ']'

Проблема возникает, когда клиент завершает соединение с конечной точкой до того, как ВСЕ результаты будут доставлены. В этом случае менеджер контекста для курсора должен закрыть курсор, что, как я понимаю в документации (https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-close.html), означает, что непрочитанные результаты сбрасываются. Тем не менее, этого не происходит, кажется, что на курсор выдается ошибка.close ():

OperationalError(-1, 'MySQL Connection not available.', None)
Traceback (most recent call last):
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/wsgi.py", line 147, in respond
    self.write(chunk)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/wsgi.py", line 228, in write
    self.req.write(chunk)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/server.py", line 1112, in write
    self.conn.wfile.write(chunk)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/makefile.py", line 36, in write
    self._flush_unlocked()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/makefile.py", line 45, in _flush_unlocked
    n = self.raw.write(bytes(self._write_buf))
  File "/usr/lib/python3.6/socket.py", line 604, in write
    return self._sock.send(b)
BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "api.py", line 81, in getKeyConnectionCursor
    yield cursor
  File "api.py", line 699, in segmentsInComputationGenerator
    yield output
GeneratorExit

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "api.py", line 72, in getKeyConnection
    yield cnx
  File "api.py", line 83, in getKeyConnectionCursor
    cursor.close()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/cursor.py", line 388, in close
    self._connection.handle_unread_result()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/connection.py", line 1063, in handle_unread_result
    raise errors.InternalError("Unread result found")
mysql.connector.errors.InternalError: Unread result found

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/server.py", line 1252, in communicate
    req.respond()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/server.py", line 1056, in respond
    self.server.gateway(self).respond()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/wsgi.py", line 152, in respond
    response.close()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/werkzeug/wsgi.py", line 874, in close
    callback()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/werkzeug/wrappers.py", line 1164, in close
    self.response.close()
  File "api.py", line 700, in segmentsInComputationGenerator
    yield ']'
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "api.py", line 83, in getKeyConnectionCursor
    cursor.close()
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "api.py", line 74, in getKeyConnection
    cnx.close()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/pooling.py", line 118, in close
    cnx.reset_session()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/connection.py", line 713, in reset_session
    raise errors.OperationalError("MySQL Connection not available.")
mysql.connector.errors.OperationalError: MySQL Connection not available.

Кажется, что курсор ожидает, что не будет непрочитанных результатов, когда cursor.close () вызываемый, что противоречит интерпретации документации , Как правильно удалить непрочитанные результаты из курсора в менеджере контекста?

...