NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #4144 most downloaded on PyPI
The fastest asyncio MySQL/MariaDB driver for Python
Last release 13 days ago
21 Sep 2026
Release timing varies
gaps range from 2 weeks to 13 months
Nearly every release is documented
notes for 24 of 24 stable releases
Nothing withdrawn
no release was ever pulled
6 years old
28 releases · first in 2021
One column per quarter.
Fix read_timeout losing data, EOF, or error notifications when the transport callback runs before the read waiter is registered, notably on Python 3.9
read_timeout losing data, EOF, or error notifications when the transport callbackPool.wait_closed() is cancelled, and serializeOperationalError for writes to closed transports (including uvloop) sopool_pre_ping can recognize the disconnect and replace the connection (#158).Pool.wait_closed() blocking forever when the last connection was released while inside aconnect()Pool.terminate() not notifying wait_closed() waiters parked on the pool's condition, sowait_closed() call already in flight when terminate() runs would hang forever even thoughFull changelog: v0.2.14...v0.2.15
Set the PEP 249 module globals apilevel , threadsafety and paramstyle , and export the exception classes from asyncmy ( #77 ).
apilevel, threadsafety and paramstyle, and export theasyncmy (#77).MySQLError.sqlstate; args is unchanged (#138).ssl=True silently connecting in plaintext: it now builds a default TLS context, and anTrue, a dict, nor an ssl.SSLContext raises ValueErrorConnection.cursor() is now awaitable, so aiomysql's cur = await conn.cursor() spellingconn.cursor() and async with conn.cursor() are unaffected (#145).Gtid.__hash__ / GtidSet.__hash__ — defining __eq__ had made Gtid unhashable, whichGtidSet (and therefore GTID replication) unusable (#59).Connection/Cursor safeasyncmy/version.py, so pyproject.toml is the single source and the _client_version thepy.typed plus .pyi stubs for the Cython modules, somake stubs regenerates them andmake check runs stubtest, which fails on any drift from the compiled modules (#78).connect(password_creator=...): a callable consulted before every connection attempt,ping(reconnect=True) never actually reconnecting: _connected stayed set when the pingconnect() returned early and the follow-up ping ran on the dead connection.connect(query_callback=...), called as callback(cursor, query, elapsed_ms) after everyecho's hardcoded INFO line — aexecutemany/callproc report once perecho, which is unchanged (#81, #69).connect(sock=...): speak MySQL over a socket the caller has already connected. Combinedssl the TLS handshake runs before the MySQL handshake instead of being negotiated_secure was only set for unix sockets, socaching_sha2_password full authentication over TLS took the RSA branch instead of sending the1045 Access denied (#117).CLIENT_DEPRECATE_EOF negotiated: one packet less per result set and per prepare
Binary protocol release — server-side prepared statements land, and the receive path goes zero-copy. On the cross-language benchmark asyncmy's binary scan (22.9ms/50k rows) is now the fastest, ahead of go-sql-driver (32ms) and mysql_async (48ms).
stmt = await conn.prepare("SELECT id, name FROM users WHERE id = ?")
result = await stmt.execute((42,))pool = await asyncmy.create_pool(stmt_cache_size=128, ...)Plain cursor.execute("... %s ...", args) automatically runs as cached server-side prepared statements — ORMs benefit with zero code changes (36.9ms → 25.3ms on 50k-row cursor scans). Unpreparable queries fall back to the text protocol silently. Opt-in because FLOAT columns return the exact stored value under the binary protocol.
asyncio.BufferedProtocol replaces StreamReader: incoming bytes land directly in the parse buffer (zero-copy receive, no per-read Future round-trips)CLIENT_DEPRECATE_EOF negotiated: one packet less per result set and per prepareCOM_STMT_BULK_EXECUTE: executemany binds all rows in one round-trip when the statement cache is enabled (also stmt.execute_bulk(rows))LOAD DATA LOCAL INFILE sending (await on a non-coroutine) and add write backpressureconftest.py ignoring a non-default MYSQL_PORTFull Changelog: v0.2.12...v0.2.13
stmt = await conn.prepare(sql),
await stmt.execute(args). Parameters are sent in binary form (no client-side escaping)
and results are parsed from the binary protocol — no text parsing for numeric/temporal
columns. Large scans are ~35% faster than the text protocol; on the cross-language
benchmark asyncmy's binary scan is now the fastest, ahead of go-sql-driver and mysql_async.connect(stmt_cache_size=N) makes plain
cursor.execute("... %s ...", args) run as cached server-side prepared statements
(binary protocol) with silent text-protocol fallback for unpreparable queries.
Opt-in because FLOAT columns return the exact stored value under the binary protocol.asyncio.BufferedProtocol: incoming bytes land
directly in the parse buffer (zero-copy receive, no per-read Future round-trips).LOAD DATA LOCAL INFILE sending (await on a non-coroutine) and add write backpressure.CLIENT_DEPRECATE_EOF: one packet less per result set and per prepare
(both MySQL 5.7.5+ and MariaDB support it; legacy EOF path kept for older servers).COM_STMT_BULK_EXECUTE — executemany binds all rows in binary
form in one round-trip when stmt_cache_size is enabled (automatic text fallback);
also available explicitly via stmt.execute_bulk(rows).conftest.py ignoring a non-default MYSQL_PORT.Remove unsafe escape_dict — dict keys could reach SQL unescaped ( CVE-2025-65896 ). ( #134 , #135 , thanks @Cycloctane )
Major performance release — the protocol core was rebuilt around direct C-level parsing. asyncmy now ranks #1 in every benchmark, including against the C-based synchronous mysqlclient. Large result sets are 5-15x faster than 0.2.11.
parse_rows_from_buffer) with pointer-based protocol reads — no struct calls on the hot pathPyUnicode_DecodeUTF8, PyTuple_New)int/float/datetime parse straight from wire bytescdivision, bounds-check-free parsingSee benchmark/README.md for methodology and numbers.
escape_dict — dict keys could reach SQL unescaped (CVE-2025-65896). (#134, #135, thanks @Cycloctane)AttributeError: 'Connection' object has no attribute 'ssl' in sha256_password auth branch. (#147, #148, thanks @shychee)OKPacketWrapper.message containing 2 stray bytes (read_struct position bug).LoadLocalPacketWrapper missing attribute declarations (LOAD DATA LOCAL crash).rowcount/insert_id on unbuffered cursors and Windows.OverflowError when escaping ints outside the signed 64-bit range, e.g. unsigned BIGINT 2**64-1. (#35, #127)INSERT ... AS alias ON DUPLICATE KEY UPDATE syntax in executemany. (#116, #120, thanks @MarkReedZ)setuptools instead of deprecated distutils in build. (#106, thanks @tijuca)build.py to build_cython.py — it shadowed the PyPA build module under cibuildwheel v3's python -m build frontend, breaking wheel builds.Full Changelog: v0.2.11...v0.2.12
OKPacketWrapper.message containing 2 stray bytes (read_struct position bug).LoadLocalPacketWrapper missing attribute declarations (LOAD DATA LOCAL crash).rowcount/insert_id on unbuffered cursors and Windows.escape_dict — dict keys could reach SQL unescaped (CVE-2025-65896). (#134, #135, thanks @Cycloctane)AttributeError: 'Connection' object has no attribute 'ssl' in sha256_password auth branch. (#147, #148, thanks @shychee)INSERT ... AS alias ON DUPLICATE KEY UPDATE syntax in executemany. (#116, #120, thanks @MarkReedZ)OverflowError when escaping ints outside the signed 64-bit range, e.g. unsigned BIGINT 2**64-1. (#35, #127)setuptools instead of deprecated distutils in build. (#106, thanks @tijuca)Add missing 3.13 whl by @dev-jelly in #123
Full Changelog: v0.2.10...v0.2.11
fix: missing wheel(*.whl) for Python 3.12 by @waketzheng in #97
Full Changelog: v0.2.9...v0.2.10
*.whl for Python 3.12 (#94)Full Changelog : v0.2.9...v0.2.10-rc1
Full Changelog: v0.2.9...v0.2.10-rc1
Added support for SSL context creation via ssl parameter using a dictionary containing mysql_ssl_set parameters.
Fix sudden loss of float precision.
Fix pool echo parameter not apply to create connection.
echo parameter not apply to create connection. (#62)Fix sudden loss of float precision.
Fix No module named 'asyncmy.connection'.
No module named 'asyncmy.connection'.Nothing published for this version
Revert TIME return datetime.time object.
TIME return datetime.time object. (#37)Fix escape_string for enum type.
escape_string for enum type. (#30)TIME return datetime.time object.- Fix escape_sequence. (#20) - Fix connection.autocommit. (#21) - Fix _clear_result.
escape_sequence. (#20)connection.autocommit. (#21)_clear_result. (#22)- Fix bug. (#18) - Fix replication error.
- Fix binlogstream await. (#12) - Remove loop argument. (#15) - Fix unix_socket connect.
binlogstream await. (#12)loop argument. (#15)unix_socket connect. (#17)- Fix cursor.close. ## 0.1
cursor.close.Fix bug replication and now don't need to connect manual.
pool_recycle.echo option.Fix async fetchone, fetchall, and fetchmany.
fetchone, fetchall, and fetchmany. (#7)- Fix negative pk.
- Bug fix.
- Remove byte2int and int2byte. - Fix warning for sql_mode.
- Add replication support.
- Fix pool.
- Fix build error.
- Fix build error.
Your coding agent can read these notes before it upgrades. Set up the MCP server →