Async/await support in MariaDB Connector/Python 2.0 enables non-blocking database operations via asyncConnect, AsyncCursor, and create_async_pool for asyncio-based Python applications.
MariaDB Connector/Python 2.0 introduces native async/await support for asynchronous database operations. This enables efficient database access in async applications like FastAPI, Starlette, and other asyncio-based frameworks.
API Reference
Connection API - Connection parameters, methods, and attributes
Cursor API - Cursor parameters, methods, and attributes
async with await mariadb.asyncConnect("mariadb://localhost/mydb") as conn:
async with conn.cursor() as cursor:
# Simple query
await cursor.execute("SELECT COUNT(*) FROM users")
count = await cursor.fetchone()
print(f"Total users: {count[0]}")
# Parameterized query
await cursor.execute(
"SELECT name, email FROM users WHERE id = ?",
(user_id,)
)
user = await cursor.fetchone()
async with conn.cursor() as cursor:
await cursor.execute("SELECT * FROM users")
# Fetch one row
row = await cursor.fetchone()
# Fetch multiple rows
rows = await cursor.fetchmany(10)
# Fetch all remaining rows
all_rows = await cursor.fetchall()
# Iterate over results
await cursor.execute("SELECT * FROM users")
async for row in cursor:
print(row)
async with conn.cursor() as cursor:
# Single insert
await cursor.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
("Alice", "alice@example.com")
)
await conn.commit()
# Get last inserted ID
print(f"Inserted user ID: {cursor.lastrowid}")
async with conn.cursor() as cursor:
data = [
("Alice", "alice@example.com"),
("Bob", "bob@example.com"),
("Charlie", "charlie@example.com")
]
await cursor.executemany(
"INSERT INTO users (name, email) VALUES (?, ?)",
data
)
await conn.commit()
print(f"Inserted {cursor.rowcount} rows")
async with await mariadb.asyncConnect("mariadb://localhost/mydb") as conn:
try:
async with conn.cursor() as cursor:
# Start transaction (autocommit is False by default)
await cursor.execute(
"UPDATE accounts SET balance = balance - ? WHERE id = ?",
(100, 1)
)
await cursor.execute(
"UPDATE accounts SET balance = balance + ? WHERE id = ?",
(100, 2)
)
# Commit transaction
await conn.commit()
except mariadb.Error as e:
# Rollback on error
await conn.rollback()
print(f"Transaction failed: {e}")
raise
import asyncio
import mariadb
async def main():
# Create pool
pool = await mariadb.create_async_pool(
host="localhost",
user="user",
password="password",
database="mydb",
min_size=5, # Minimum connections
max_size=20, # Maximum connections
ping_threshold=0.25 # Ping if idle > 250ms
)
# Use pool
async with await pool.acquire() as conn:
async with conn.cursor() as cursor:
await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
row = await cursor.fetchone()
print(row)
# Close pool when done
await pool.close()
asyncio.run(main())
pool = await mariadb.create_async_pool(
"mariadb://user:password@localhost/mydb",
min_size=10,
max_size=50
)
pool = await mariadb.create_async_pool(
host="localhost",
user="user",
password="password",
database="mydb",
min_size=5, # Minimum pool size
max_size=20, # Maximum pool size
ping_threshold=0.25, # Ping connections idle > 250ms
binary=True, # Use binary protocol by default
autocommit=False # Transaction mode
)
from fastapi import FastAPI, HTTPException
from contextlib import asynccontextmanager
import mariadb
# Global pool variable
pool = None
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: Create pool
global pool
pool = await mariadb.create_async_pool(
"mariadb://user:password@localhost/mydb",
min_size=10,
max_size=50
)
yield
# Shutdown: Close pool
await pool.close()
app = FastAPI(lifespan=lifespan)
@app.get("/users/{user_id}")
async def get_user(user_id: int):
async with await pool.acquire() as conn:
async with conn.cursor(dictionary=True) as cursor:
await cursor.execute(
"SELECT id, name, email FROM users WHERE id = ?",
(user_id,)
)
user = await cursor.fetchone()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.post("/users")
async def create_user(name: str, email: str):
async with await pool.acquire() as conn:
async with conn.cursor() as cursor:
try:
await cursor.execute(
"INSERT INTO users (name, email) VALUES (?, ?)",
(name, email)
)
await conn.commit()
return {
"id": cursor.lastrowid,
"name": name,
"email": email
}
except mariadb.IntegrityError:
await conn.rollback()
raise HTTPException(
status_code=400,
detail="User with this email already exists"
)
import asyncio
import mariadb
async def main():
try:
conn = await mariadb.asyncConnect(
"mariadb://user:password@localhost/mydb"
)
except mariadb.Error as e:
print(f"Connection error: {e}")
return
try:
async with conn.cursor() as cursor:
await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
row = await cursor.fetchone()
except mariadb.DatabaseError as e:
print(f"Database error: {e}")
except mariadb.ProgrammingError as e:
print(f"Programming error: {e}")
finally:
await conn.close()
asyncio.run(main())
async with conn.cursor(dictionary=True) as cursor:
await cursor.execute("SELECT id, name, email FROM users WHERE id = ?", (1,))
user = await cursor.fetchone()
print(user["name"]) # Access by column name
async with conn.cursor(named_tuple=True) as cursor:
await cursor.execute("SELECT id, name, email FROM users WHERE id = ?", (1,))
user = await cursor.fetchone()
print(user.name) # Access as attribute
async with conn.cursor(buffered=False) as cursor:
await cursor.execute("SELECT * FROM large_table")
# Fetch rows one at a time
async for row in cursor:
process_row(row)
# Only one row in memory at a time
# Connection-level binary protocol
conn = await mariadb.asyncConnect(
"mariadb://localhost/mydb?binary=true"
)
async with conn.cursor() as cursor:
# All queries use binary protocol
await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
row = await cursor.fetchone()
# Or per-cursor
async with conn.cursor(binary=True) as cursor:
await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
row = await cursor.fetchone()
# Good: Connection pool
pool = await mariadb.create_async_pool(
"mariadb://localhost/mydb",
min_size=10,
max_size=50
)
# Bad: Creating connections per request
async def handle_request():
conn = await mariadb.asyncConnect("mariadb://localhost/mydb")
# ... use connection
await conn.close()
async def main():
async with await mariadb.asyncConnect("mariadb://localhost/mydb") as conn:
async with conn.cursor() as cursor:
await cursor.execute("SELECT * FROM users WHERE id = ?", (1,))
row = await cursor.fetchone()
asyncio.run(main())