Search code examples
aiohttp

Why aiomysql locks the table even when using context manager?


I noticed that even I execute sql statements inside "with" context manager, after the request is finished, the table queried still locked and I can't execute "truncate" on it until I stop the event loop.

Here is example of my code:

import logging
import asyncio
import aiomysql
from aiohttp import web
from aiomysql.cursors import DictCursor


logging.basicConfig(level=logging.DEBUG)

async def index(request):
    async with request.app["mysql"].acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute("SELECT * FROM my_table")
            lines = await cur.fetchall()

    return web.Response(text='Hello Aiohttp!')

async def get_mysql_pool(loop):
    pool = await aiomysql.create_pool(
        host="localhost",
        user="test",
        password="test",
        db="test",
        cursorclass=DictCursor,
        loop=loop
    )

    return pool

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    mysql = loop.run_until_complete(get_mysql_pool(loop))
    app = web.Application(loop=loop, debug=True)
    app["mysql"] = mysql
    app.router.add_get("/", index)
    web.run_app(app)

After executing curl 'http://localhost:8080/', I'm connecting to mysql server with mysql cli and try to execute "truncate my_table" - it won't finish until I stop aiohttp. How to change this behavior?


Solution

  • Locks held because connection is not in autocommit mode by default. Adding autocommit=True should solve the issue.

    pool = await aiomysql.create_pool(
        host="localhost",
        user="test",
        password="test",
        db="test",
        autocommit=True,
        cursorclass=DictCursor,
        loop=loop)
    

    Alternatively it is possible to release transaction by explicit command:

    await cur.execute("COMMIT;")
    

    Primary purpose of context managers here is to close cursor, not to commit transaction.

    aiomysql has SQLAlchemy.core extension with context manager support for transactions, see example here:

    https://github.com/aio-libs/aiomysql/blob/93aa3e5f77d77ad5592c3e9519cfc9f9587bf9ac/tests/pep492/test_async_with.py#L214-L234