Skip to content

Commit 112c11c

Browse files
committed
fix closed MySQL 8.0 connections not always being detected properly
ensure connections are closed properly when the server connection was lost
1 parent 4274fbc commit 112c11c

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

CHANGES.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
Changes
22
-------
33

4+
pending release
5+
^^^^^^^^^^^^^^^^^^^
6+
7+
* Fix timed out MySQL 8.0 connections raising InternalError rather than OperationalError #660
8+
* Fix timed out MySQL 8.0 connections being returned from Pool #660
9+
* Ensure connections are properly closed before raising OperationalError when the server connection is lost #660
10+
11+
412
0.0.22 (2021-11-14)
513
^^^^^^^^^^^^^^^^^^^
614

aiomysql/connection.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from pymysql.constants import SERVER_STATUS
1616
from pymysql.constants import CLIENT
1717
from pymysql.constants import COMMAND
18+
from pymysql.constants import CR
1819
from pymysql.constants import FIELD_TYPE
1920
from pymysql.util import byte2int, int2byte
2021
from pymysql.converters import (escape_item, encoders, decoders,
@@ -470,7 +471,7 @@ async def set_charset(self, charset):
470471

471472
async def _connect(self):
472473
# TODO: Set close callback
473-
# raise OperationalError(2006,
474+
# raise OperationalError(CR.CR_SERVER_GONE_ERROR,
474475
# "MySQL server has gone away (%r)" % (e,))
475476
try:
476477
if self._unix_socket and self._host in ('localhost', '127.0.0.1'):
@@ -569,6 +570,13 @@ async def _read_packet(self, packet_type=MysqlPacket):
569570
# we increment in both write_packet and read_packet. The count
570571
# is reset at new COMMAND PHASE.
571572
if packet_number != self._next_seq_id:
573+
if packet_number == 0:
574+
# MySQL 8.0 sends error packet with seqno==0 when shutdown
575+
self.close()
576+
raise OperationalError(
577+
CR.CR_SERVER_LOST,
578+
"Lost connection to MySQL server during query")
579+
572580
raise InternalError(
573581
"Packet sequence number wrong - got %d expected %d" %
574582
(packet_number, self._next_seq_id))
@@ -596,10 +604,12 @@ async def _read_bytes(self, num_bytes):
596604
data = await self._reader.readexactly(num_bytes)
597605
except asyncio.IncompleteReadError as e:
598606
msg = "Lost connection to MySQL server during query"
599-
raise OperationalError(2013, msg) from e
607+
self.close()
608+
raise OperationalError(CR.CR_SERVER_LOST, msg) from e
600609
except (IOError, OSError) as e:
601610
msg = "Lost connection to MySQL server during query (%s)" % (e,)
602-
raise OperationalError(2013, msg) from e
611+
self.close()
612+
raise OperationalError(CR.CR_SERVER_LOST, msg) from e
603613
return data
604614

605615
def _write_bytes(self, data):

aiomysql/pool.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ async def _acquire(self):
143143
await self._cond.wait()
144144

145145
async def _fill_free_pool(self, override_min):
146-
# iterate over free connections and remove timeouted ones
146+
# iterate over free connections and remove timed out ones
147147
free_size = len(self._free)
148148
n = 0
149149
while n < free_size:
@@ -152,6 +152,11 @@ async def _fill_free_pool(self, override_min):
152152
self._free.pop()
153153
conn.close()
154154

155+
# TODO: fixme, we should not use internal attributes
156+
elif conn._reader._eof:
157+
self._free.pop()
158+
conn.close()
159+
155160
elif (self._recycle > -1 and
156161
self._loop.time() - conn.last_usage > self._recycle):
157162
self._free.pop()

0 commit comments

Comments
 (0)