aiomysql Documentation

repository·main·Indexed 23 days ago

https://github.com/aio-libs/aiomysql

An asynchronous MySQL driver for Python's asyncio framework, designed as a drop-in async replacement for PyMySQL with an API similar to aiopg. It provides functionality for establishing direct connections via connect(), managing connection pools with create_pool(), and utilizing various cursor types including Cursor, DictCursor, SSCursor (server-side), and SSDictCursor. The library includes support for transaction management, bulk inserts via executemany(), and automatic JSON parsing through DeserializationCursor.

Tokens
12K
Snippets
22
Records
63
Agent score
82%

What's inside aiomysql

  1. What is aiomysql?

    main
    aiomysql is an asynchronous driver for accessing MySQL databases from the asyncio framework. It is built by extending PyMySQL, replacing underlying I/O calls with asynchronous versions. It aims to provide an API and developer experience similar to the aiopg library.
  2. Use the Connection object to manage sessions

    main

    The aiomysql.Connection object represents a socket with a MySQL server. Its interface is nearly identical to pymysql.connection, but all methods are coroutines and must be awaited.

    Key capabilities include:

    • Creating cursors via cursor().
    • Managing transactions with begin(), commit(), and rollback().
    • Controlling autocommit mode via autocommit(value) and get_autocommit().
    • Switching databases with select_db(db).
    • Closing the connection via close() or ensure_closed().
  3. Managing database transactions

    main

    Transactions in aiomysql.sa are managed via Transaction objects obtained from an SAConnection. You control transaction boundaries using .commit() and .rollback().

    Standard Transactions

    Use await conn.begin() to start a transaction.

    async with engine.acquire() as conn:
        trans = await conn.begin()
        try:
            await conn.execute("insert into x (a, b) values (1, 2)")
        except Exception:
            await trans.rollback()
        else:
            await trans.commit()

    Nested Transactions (SAVEPOINT)

    Use await conn.begin_nested() to create a NestedTransaction. This represents a MySQL SAVEPOINT. The interface is identical to a standard Transaction.

    Two-Phase Transactions (XA)

    Use await conn.begin_twophase() to create a TwoPhaseTransaction. This is used for distributed transactions. In addition to commit() and rollback(), you must call the .prepare() coroutine before committing.

    TwoPhaseTransaction properties:

    • xid: Returns the two-phase transaction ID.
    • prepare(): Prepares the transaction for commit.
  4. Use SSCursor and SSDictCursor for large datasets

    main

    Standard cursors buffer the entire result set in memory. For very large queries or slow networks, use unbuffered cursors:

    • SSCursor: An unbuffered cursor. It fetches rows as needed, significantly reducing client-side memory usage.
    • SSDictCursor: An unbuffered cursor that returns results as dictionaries.

    Limitations of Unbuffered Cursors:

    • You cannot determine the total row count without iterating through the entire set.
    • Backward scrolling is not supported.
    • fetchall() is inefficient as it still fetches all rows one by one.
  5. How aiomysql works compared to DBAPI

    main
    aiomysql provides an asynchronous interface that mirrors the standard synchronous DBAPI used by most relational database modules. The primary difference is that you must use await when calling methods on connection and cursor objects (e.g., await conn.execute() instead of conn.execute()).
  6. Manage transactions and autocommit

    main

    By default, autocommit is set to False. This means you must manually call await conn.commit() on the Connection object to persist changes made via cur.execute().

    Alternatively, you can enable automatic commits by passing autocommit=True to the aiomysql.connect() method.

  7. How to use the default Cursor

    main

    A Cursor allows you to execute MySQL commands within a database session. Cursors are created via Connection.cursor(). Note that cursors created from the same connection share the same session; changes made by one cursor are immediately visible to others on that same connection.

    To use a cursor, you typically follow this lifecycle: connect, create cursor, execute query, fetch results, close cursor, and close connection.

    import asyncio
    import aiomysql
    
    loop = asyncio.get_event_loop()
    
    async def test_example():
        conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                      user='root', password='',
                                      db='mysql', loop=loop)
    
        # create default cursor
        cursor = await conn.cursor()
    
        # execute sql query
        await cursor.execute("SELECT Host, User FROM user")
    
        # fetch all results
        r = await cursor.fetchall()
    
        # detach cursor from connection
        await cursor.close()
    
        # close connection
        conn.close()
    
    loop.run_until_complete(test_example())
  8. Use connection pools with aiomysql.create_pool()

    main

    Instead of managing individual Connection objects, use aiomysql.create_pool() to manage a pool of connections. This is the recommended way to handle multiple database operations efficiently.

    To use a pool:

    1. Create the pool using await aiomysql.create_pool(...).
    2. Acquire a connection using async with pool.acquire() as conn:.
    3. Use the connection to create a cursor: async with conn.cursor() as cur:.
    4. Close the pool using pool.close() and wait for it to finish with await pool.wait_closed().
    import asyncio
    import aiomysql
    
    loop = asyncio.get_event_loop()
    
    async def go():
        pool = await aiomysql.create_pool(host='127.0.0.1', port=3306,
                                          user='root', password='',
                                          db='mysql', loop=loop, autocommit=False)
    
        async with pool.acquire() as conn:
            async with conn.cursor() as cur:
                await cur.execute("SELECT 10")
                (r,) = await cur.fetchone()
                assert r == 10
        pool.close()
        await pool.wait_closed()
    
    loop.run_until_complete(go())
  9. Use SQLAlchemy with aiomysql for SQL query building

    main

    Instead of using raw SQL strings, you can use aiomysql.sa to leverage SQLAlchemy's functional SQL layer as a query builder. This allows you to execute SQLAlchemy expressions (like table.insert() or table.select()) directly through an aiomysql engine. The API is designed to be familiar to users of aiopg_.

    import asyncio
    import sqlalchemy as sa
    from aiomysql.sa import create_engine
    
    metadata = sa.MetaData()
    
    tbl = sa.Table(
        "tbl",
        metadata,
        sa.Column("id", sa.Integer, primary_key=True),
        sa.Column("val", sa.String(255)),
    )
    
    async def go():
        engine = await create_engine(
            user="root",
            db="test_pymysql",
            host="127.0.0.1",
            password="",
        )
    
        async with engine.acquire() as conn:
            async with conn.begin() as transaction:
                await conn.execute(tbl.insert().values(val="abc"))
                await transaction.commit()
    
                res = await conn.execute(tbl.select())
                async for row in res:
                    print(row.id, row.val)
    
        engine.close()
        await engine.wait_closed()
    
    asyncio.run(go())
  10. Basic usage of aiomysql

    main

    aiomysql provides an asyncio DBAPI-like interface for MySQL. It is based on PyMySQL, so it shares the same API, but you must await method calls that perform I/O. Properties remain unchanged and do not require await.

    import asyncio
    import aiomysql
    
    loop = asyncio.get_event_loop()
    
    async def test_example():
        # Establish connection
        conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                       user='root', password='', db='mysql',
                                       loop=loop)
    
        # Create a cursor and execute a query
        cur = await conn.cursor()
        await cur.execute("SELECT Host,User FROM user")
        
        # Access metadata and fetch results
        print(cur.description)
        r = await cur.fetchall()
        print(r)
        
        # Clean up
        await cur.close()
        conn.close()
    
    loop.run_until_complete(test_example())