AsyncIO-vs-Sync-In-SessionDB
1. Core Concept
Synchronous SQLAlchemy (classic):
- Operations block the Python thread until they complete.
- Typical usage:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
Base = declarative_base()
engine = create_engine("sqlite:///test.db")
Session = sessionmaker(bind=engine)
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
# Sync usage
with Session() as session:
user = session.query(User).filter_by(name="Alice").first()
print(user.id)
Asynchronous SQLAlchemy (asyncio):
- Uses
async/await, so your code doesn’t block the event loop while waiting for the database. - Requires an async-compatible database driver, like
asyncpgfor PostgreSQL oraiosqlitefor SQLite. - Typical usage:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
import asyncio
Base = declarative_base()
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_user():
async with AsyncSessionLocal() as session:
result = await session.execute(
"SELECT * FROM users WHERE name=:name", {"name": "Alice"}
)
user = result.fetchone()
print(user)
asyncio.run(get_user())
2. Key Differences
| Aspect | Synchronous | Asynchronous |
|---|---|---|
| Execution | Blocks thread until query finishes | Non-blocking, allows other coroutines to run while waiting |
| Driver | Standard DB drivers (psycopg2, pymysql, sqlite3) | Async drivers (asyncpg, aiosqlite, aiomysql) |
| Session | Session | AsyncSession |
| Query Execution | Direct function calls: session.query().all() | await session.execute() |
| Engine | create_engine() | create_async_engine() |
| Transactions | with session.begin(): ... | async with session.begin(): ... |
| Performance | Good for single-threaded or blocking apps | Better for high-concurrency async apps (web servers, async tasks) |
| ORM Support | Full ORM | Full ORM, but you must await query results |
3. Important Notes
- Async is not faster for a single query: It mainly helps if your app is doing many concurrent DB operations, like a web server handling hundreds of requests simultaneously.
- Mixing sync and async sessions is tricky: You should generally stick to one pattern in a given context.
- Some SQLAlchemy features are slightly different in async mode:
session.execute()returns aResultobject; you usually use.fetchone(),.fetchall(), or.scalars().- Lazy loading of relationships is async too (
await user.addresses).