aiomysql 完整实战教程
本教程全覆盖 aiomysql 0.3.2 所有核心功能 ,适配 Python 3.12.10,包含数据库/表创建SQL 、逐行代码注释 、开发思路文档注释,从入门到高级实战一站式掌握。
前置准备
1. 环境安装
bash
# 安装 aiomysql(异步MySQL驱动)
pip install aiomysql==0.3.2
# 安装依赖(若缺失)
pip install pymysql
2. 基础配置
所有示例共用MySQL连接配置(根据自己的MySQL信息修改):
python
# MySQL基础配置(所有章节通用)
DB_CONFIG = {
"host": "localhost", # MySQL主机
"port": 3306, # MySQL端口
"user": "root", # MySQL用户名
"password": "你的MySQL密码", # MySQL密码
"db": "aiomysql_demo", # 数据库名称(后续创建)
"charset": "utf8mb4", # 字符集(支持emoji)
"autocommit": False # 默认关闭自动提交
}
目录(全章节)
- 章节1:数据库/表初始化(SQL+代码)
- 章节2:基础连接与关闭(核心连接池/单连接)
- 章节3:同步式CRUD(基础增删改查)
- 章节4:异步事务管理(提交/回滚)
- 章节5:批量操作(批量插入/更新/删除)
- 章节6:游标操作(DictCursor/SSCursor/SSDictCursor)
- 章节7:查询结果处理(分页/排序/聚合)
- 章节8:连接池高级配置(最大连接/超时/重连)
- 章节9:异常处理与日志
- 章节10:实战:异步并发操作
章节1:数据库与表初始化
开发思路
- 先创建专用数据库,避免与其他业务数据冲突
- 创建测试表(用户表、订单表),覆盖主键、自增、唯一约束、外键、索引
- 编写异步代码执行初始化SQL,确保表结构可复用
1.1 完整创建SQL(直接复制到MySQL执行)
sql
-- 创建数据库(不存在则创建)
CREATE DATABASE IF NOT EXISTS aiomysql_demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE aiomysql_demo;
-- ==================== 1. 用户表(基础CRUD测试) ====================
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户ID(主键自增)',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`age` TINYINT UNSIGNED NULL DEFAULT 0 COMMENT '年龄',
`email` VARCHAR(100) NOT NULL COMMENT '邮箱',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_email` (`email`) COMMENT '邮箱唯一约束'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- ==================== 2. 订单表(外键+关联测试) ====================
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`order_id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '订单ID',
`user_id` INT UNSIGNED NOT NULL COMMENT '用户ID(关联user表)',
`order_no` VARCHAR(32) NOT NULL COMMENT '订单编号',
`amount` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '订单金额',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`order_id`),
UNIQUE KEY `uk_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`),
CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
1.2 异步初始化代码(自动执行SQL)
python
import asyncio
import aiomysql
# 文档注释:开发思路
# 1. 创建异步MySQL连接(不指定数据库,先创建库)
# 2. 执行创建数据库/表的SQL语句
# 3. 关闭连接,释放资源
async def init_database():
# 临时连接:不指定数据库,用于创建库和表
conn = await aiomysql.connect(
host=DB_CONFIG["host"],
port=DB_CONFIG["port"],
user=DB_CONFIG["user"],
password=DB_CONFIG["password"],
charset=DB_CONFIG["charset"]
)
# 获取异步游标
async with conn.cursor() as cur:
# 执行创建数据库SQL
await cur.execute("CREATE DATABASE IF NOT EXISTS aiomysql_demo")
# 切换到目标数据库
await cur.execute("USE aiomysql_demo")
# 创建用户表
await cur.execute("""
CREATE TABLE IF NOT EXISTS `user` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` VARCHAR(50) NOT NULL,
`age` TINYINT UNSIGNED NULL DEFAULT 0,
`email` VARCHAR(100) NOT NULL,
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
""")
# 创建订单表
await cur.execute("""
CREATE TABLE IF NOT EXISTS `order` (
`order_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`order_no` VARCHAR(32) NOT NULL,
`amount` DECIMAL(10,2) NOT NULL DEFAULT 0.00,
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`order_id`),
UNIQUE KEY `uk_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`),
CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
""")
# 提交事务
await conn.commit()
print("✅ 数据库和表初始化完成!")
# 关闭连接
conn.close()
# 执行初始化
if __name__ == "__main__":
asyncio.run(init_database())
章节2:基础连接与关闭
开发思路
- aiomysql 核心:单连接 (简单场景)+ 连接池(生产环境,推荐)
- 掌握异步上下文管理器(
async with)自动管理连接/游标 - 区分同步关闭与异步关闭,避免资源泄漏
2.1 单连接(基础用法)
python
import asyncio
import aiomysql
# 文档注释:开发思路
# 1. 单连接适合简单、一次性的数据库操作
# 2. 使用async with自动管理连接生命周期(自动创建/关闭)
# 3. 执行简单查询验证连接有效性
async def single_connection_demo():
# 异步创建并自动管理连接(退出with块自动关闭)
async with aiomysql.connect(**DB_CONFIG) as conn:
# 异步创建并自动管理游标
async with conn.cursor() as cur:
# 执行测试SQL
await cur.execute("SELECT VERSION()")
# 获取单条结果
result = await cur.fetchone()
print(f"✅ MySQL版本:{result[0]}")
print("✅ 单连接已自动关闭")
# 运行示例
asyncio.run(single_connection_demo())
2.2 连接池(生产环境必备)
python
# 文档注释:开发思路
# 1. 连接池避免频繁创建/销毁连接,提升性能
# 2. 全局创建一个连接池,所有操作复用连接
# 3. 支持最大/最小连接数、超时配置
async def create_pool():
# 创建全局连接池
pool = await aiomysql.create_pool(
host=DB_CONFIG["host"],
port=DB_CONFIG["port"],
user=DB_CONFIG["user"],
password=DB_CONFIG["password"],
db=DB_CONFIG["db"],
charset=DB_CONFIG["charset"],
autocommit=DB_CONFIG["autocommit"],
# 连接池核心配置
minsize=1, # 最小空闲连接数
maxsize=10, # 最大连接数
pool_recycle=3600 # 连接回收时间(秒),防止失效
)
return pool
async def pool_connection_demo():
# 创建连接池
pool = await create_pool()
# 从连接池获取连接(自动归还)
async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute("SELECT COUNT(*) FROM `user`")
count = await cur.fetchone()
print(f"✅ 用户表总条数:{count[0]}")
# 关闭连接池(程序退出时执行)
pool.close()
await pool.wait_closed()
print("✅ 连接池已关闭")
# 运行示例
asyncio.run(pool_connection_demo())
章节3:基础CRUD操作
开发思路
- 覆盖增(INSERT)、删(DELETE)、改(UPDATE)、查(SELECT) 核心操作
- 使用参数化查询,防止SQL注入(必须掌握)
- 区分查询结果获取:
fetchone()/fetchall()
python
import asyncio
import aiomysql
# 全局连接池(后续章节复用)
pool = None
async def init_pool():
global pool
pool = await aiomysql.create_pool(**DB_CONFIG, minsize=1, maxsize=10)
# ==================== 1. 新增数据(INSERT) ====================
async def insert_user(username, age, email):
# 文档注释:开发思路
# 1. 参数化SQL:%s 为占位符,避免SQL注入
# 2. 执行后获取自增ID(lastrowid)
# 3. 手动提交事务(autocommit=False)
async with pool.acquire() as conn:
async with conn.cursor() as cur:
sql = "INSERT INTO `user` (username, age, email) VALUES (%s, %s, %s)"
# 执行参数化SQL
await cur.execute(sql, (username, age, email))
# 获取自增主键ID
user_id = cur.lastrowid
# 提交事务
await conn.commit()
print(f"✅ 新增用户成功,ID:{user_id}")
return user_id
# ==================== 2. 查询数据(SELECT) ====================
async def query_user(user_id):
async with pool.acquire() as conn:
async with conn.cursor() as cur:
sql = "SELECT id, username, age, email FROM `user` WHERE id = %s"
await cur.execute(sql, (user_id,))
# 获取单条数据
user = await cur.fetchone()
if user:
print(f"✅ 查询到用户:{user}")
return user
print("❌ 用户不存在")
return None
# ==================== 3. 更新数据(UPDATE) ====================
async def update_user_age(user_id, new_age):
async with pool.acquire() as conn:
async with conn.cursor() as cur:
sql = "UPDATE `user` SET age = %s WHERE id = %s"
await cur.execute(sql, (new_age, user_id))
# 获取受影响行数
affect_rows = cur.rowcount
await conn.commit()
print(f"✅ 更新成功,受影响行数:{affect_rows}")
return affect_rows
# ==================== 4. 删除数据(DELETE) ====================
async def delete_user(user_id):
async with pool.acquire() as conn:
async with conn.cursor() as cur:
sql = "DELETE FROM `user` WHERE id = %s"
await cur.execute(sql, (user_id,))
affect_rows = cur.rowcount
await conn.commit()
print(f"✅ 删除成功,受影响行数:{affect_rows}")
return affect_rows
# 测试CRUD
async def crud_demo():
await init_pool()
# 1. 新增
user_id = await insert_user("张三", 20, "zhangsan@test.com")
# 2. 查询
await query_user(user_id)
# 3. 更新
await update_user_age(user_id, 22)
# 4. 删除
await delete_user(user_id)
# 关闭连接池
pool.close()
await pool.wait_closed()
asyncio.run(crud_demo())
章节4:异步事务管理
开发思路
- aiomysql 事务:手动开启→执行SQL→提交/回滚
- 异常捕获:出错则回滚,保证数据一致性
- 适用于多表关联操作(如:创建用户+创建订单)
python
import asyncio
import aiomysql
# 文档注释:开发思路
# 1. 事务场景:创建用户 + 创建订单,必须同时成功/失败
# 2. 不使用autocommit,手动控制事务
# 3. try-except-finally 确保事务提交/回滚
async def transaction_demo():
await init_pool()
async with pool.acquire() as conn:
async with conn.cursor() as cur:
try:
# 步骤1:创建用户
user_sql = "INSERT INTO `user` (username, email) VALUES (%s, %s)"
await cur.execute(user_sql, ("李四", "lisi@test.com"))
user_id = cur.lastrowid
# 步骤2:创建订单(关联用户)
order_sql = "INSERT INTO `order` (user_id, order_no, amount) VALUES (%s, %s, %s)"
await cur.execute(order_sql, (user_id, "ORDER20260325001", 99.99))
# 无异常,提交事务
await conn.commit()
print("✅ 事务提交成功:用户+订单创建完成")
except Exception as e:
# 出现异常,回滚事务
await conn.rollback()
print(f"❌ 事务回滚:{str(e)}")
finally:
# 关闭连接池
pool.close()
await pool.wait_closed()
asyncio.run(transaction_demo())
章节5:批量操作
开发思路
- 批量操作比循环单条执行效率提升10倍以上
- 使用
executemany()执行批量SQL - 支持批量插入、批量更新、批量删除
python
import asyncio
import aiomysql
# ==================== 批量插入 ====================
async def batch_insert_users():
await init_pool()
async with pool.acquire() as conn:
async with conn.cursor() as cur:
sql = "INSERT INTO `user` (username, age, email) VALUES (%s, %s, %s)"
# 批量数据(列表套元组)
users = [
("王五", 25, "wangwu@test.com"),
("赵六", 28, "zhaoliu@test.com"),
("钱七", 23, "qianqi@test.com")
]
# 批量执行
await cur.executemany(sql, users)
await conn.commit()
print(f"✅ 批量插入成功,条数:{cur.rowcount}")
pool.close()
await pool.wait_closed()
# ==================== 批量更新 ====================
async def batch_update_age():
await init_pool()
async with pool.acquire() as conn:
async with conn.cursor() as cur:
sql = "UPDATE `user` SET age = age + 1 WHERE id IN %s"
await cur.execute(sql, ((2, 3, 4),)) # 批量更新ID=2/3/4的用户
await conn.commit()
print(f"✅ 批量更新成功,条数:{cur.rowcount}")
pool.close()
await pool.wait_closed()
# 测试批量操作
asyncio.run(batch_insert_users())
章节6:游标类型
aiomysql 支持4种游标,覆盖所有业务场景:
- 默认游标:返回元组
- DictCursor:返回字典(推荐,字段名直观)
- SSCursor:流式游标(大数据量,不加载全部到内存)
- SSDictCursor:流式字典游标
python
import asyncio
import aiomysql
from aiomysql import DictCursor, SSCursor, SSDictCursor
# 文档注释:开发思路
# 1. DictCursor:结果转字典,开发更友好
# 2. 流式游标:处理百万级数据,避免内存溢出
async def cursor_demo():
await init_pool()
# 1. DictCursor(字典游标)
async with pool.acquire() as conn:
async with conn.cursor(DictCursor) as cur:
await cur.execute("SELECT id, username FROM `user` LIMIT 2")
users = await cur.fetchall()
print("✅ 字典游标结果:", users) # [{"id":1, "username":"张三"}, ...]
# 2. 流式游标(大数据量)
async with pool.acquire() as conn:
async with conn.cursor(SSCursor) as cur:
await cur.execute("SELECT * FROM `user`")
# 逐行获取(不占用大量内存)
async for row in cur:
print("流式游标行数据:", row)
pool.close()
await pool.wait_closed()
asyncio.run(cursor_demo())
章节7:查询结果高级处理
开发思路
- 覆盖分页、排序、聚合函数、多表关联查询
- 处理大数据量查询,避免内存溢出
- 规范查询结果返回格式
python
import asyncio
import aiomysql
from aiomysql import DictCursor
# ==================== 1. 分页查询 ====================
async def page_query(page=1, size=10):
await init_pool()
async with pool.acquire() as conn:
async with conn.cursor(DictCursor) as cur:
sql = "SELECT id, username FROM `user` LIMIT %s OFFSET %s"
await cur.execute(sql, (size, (page-1)*size))
data = await cur.fetchall()
print(f"✅ 第{page}页数据:{data}")
pool.close()
await pool.wait_closed()
# ==================== 2. 聚合查询 ====================
async def aggregate_query():
await init_pool()
async with pool.acquire() as conn:
async with conn.cursor(DictCursor) as cur:
# 查询平均年龄、最大年龄、总人数
sql = "SELECT AVG(age) avg_age, MAX(age) max_age, COUNT(*) total FROM `user`"
await cur.execute(sql)
result = await cur.fetchone()
print("✅ 聚合结果:", result)
pool.close()
await pool.wait_closed()
# ==================== 3. 多表关联查询 ====================
async def join_query():
await init_pool()
async with pool.acquire() as conn:
async with conn.cursor(DictCursor) as cur:
# 用户+订单关联查询
sql = """
SELECT u.username, o.order_no, o.amount
FROM `user` u
LEFT JOIN `order` o ON u.id = o.user_id
WHERE u.id = %s
"""
await cur.execute(sql, (1,))
result = await cur.fetchall()
print("✅ 关联查询结果:", result)
pool.close()
await pool.wait_closed()
# 测试
asyncio.run(page_query(1, 2))
章节8:连接池高级配置
开发思路
- 生产环境优化连接池:最大连接、超时、重连、心跳
- 防止连接失效(MySQL 8小时断开问题)
- 支持动态配置连接池参数
python
import asyncio
import aiomysql
async def advanced_pool():
# 高级连接池配置
pool = await aiomysql.create_pool(
**DB_CONFIG,
minsize=2, # 最小空闲连接
maxsize=20, # 最大连接(根据服务器配置调整)
pool_recycle=300, # 5分钟回收一次连接
connect_timeout=10, # 连接超时时间(秒)
idle_timeout=300, # 空闲连接超时时间
cursorclass=DictCursor # 默认字典游标
)
print("✅ 高级连接池创建成功")
# 测试连接
async with pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute("SELECT 1")
print("✅ 连接池心跳正常")
# 关闭
pool.close()
await pool.wait_closed()
asyncio.run(advanced_pool())
章节9:异常处理与日志
开发思路
- 捕获 aiomysql 所有常见异常:
OperationalError/ProgrammingError/IntegrityError - 集成日志,记录SQL执行、异常、慢查询
- 统一异常处理,提升代码健壮性
python
import asyncio
import logging
import aiomysql
from aiomysql import OperationalError, ProgrammingError, IntegrityError
# 配置日志
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
async def exception_demo():
await init_pool()
try:
async with pool.acquire() as conn:
async with conn.cursor() as cur:
# 测试:重复插入邮箱(唯一约束冲突)
await cur.execute("INSERT INTO `user` (username, email) VALUES ('测试', 'zhangsan@test.com')")
await conn.commit()
except IntegrityError as e:
logger.error(f"❌ 数据约束错误:{e}") # 唯一键/外键冲突
except OperationalError as e:
logger.error(f"❌ 连接错误:{e}") # 连接失败/断开
except ProgrammingError as e:
logger.error(f"❌ SQL语法错误:{e}") # SQL写错
except Exception as e:
logger.error(f"❌ 未知错误:{e}")
finally:
pool.close()
await pool.wait_closed()
asyncio.run(exception_demo())
章节10:实战:异步并发操作
开发思路
- 利用 asyncio 实现并发查询/插入,大幅提升效率
- 多任务并发操作数据库,连接池自动分配连接
- 生产环境:并发批量处理数据、异步接口开发
python
import asyncio
import aiomysql
from aiomysql import DictCursor
# 并发查询用户
async def concurrent_query(user_ids):
await init_pool()
# 创建并发任务
tasks = [query_user(user_id) for user_id in user_ids]
# 批量执行
results = await asyncio.gather(*tasks)
print("✅ 并发查询结果:", results)
pool.close()
await pool.wait_closed()
# 测试:同时查询ID=1/2/3的用户
asyncio.run(concurrent_query([1, 2, 3]))
章节11:完整工具类(生产可用)
开发思路
- 封装 aiomysql 所有功能为单例工具类
- 支持连接池、事务、CRUD、异常处理
- 直接复制到项目中使用
python
import asyncio
import aiomysql
from aiomysql import DictCursor
class AioMysqlUtil:
"""
aiomysql 工具类(生产环境单例版)
覆盖:连接池、CRUD、事务、批量操作、异常处理
"""
_instance = None
_pool = None
def __new__(cls, *args, **kwargs):
# 单例模式
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
async def init_pool(self, config):
"""初始化连接池"""
if not self._pool:
self._pool = await aiomysql.create_pool(
**config,
cursorclass=DictCursor,
minsize=1,
maxsize=10
)
async def execute(self, sql, params=None):
"""执行增删改SQL"""
async with self._pool.acquire() as conn:
async with conn.cursor() as cur:
try:
await cur.execute(sql, params)
await conn.commit()
return cur.rowcount, cur.lastrowid
except Exception as e:
await conn.rollback()
raise e
async def query_one(self, sql, params=None):
"""查询单条数据"""
async with self._pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute(sql, params)
return await cur.fetchone()
async def query_all(self, sql, params=None):
"""查询多条数据"""
async with self._pool.acquire() as conn:
async with conn.cursor() as cur:
await cur.execute(sql, params)
return await cur.fetchall()
async def close(self):
"""关闭连接池"""
self._pool.close()
await self._pool.wait_closed()
# 测试工具类
async def test_util():
db = AioMysqlUtil()
await db.init_pool(DB_CONFIG)
# 查询
data = await db.query_one("SELECT * FROM `user` LIMIT 1")
print("工具类查询:", data)
await db.close()
asyncio.run(test_util())
总结
- 核心知识点 :本教程全覆盖 aiomysql 0.3.2 连接池、CRUD、事务、游标、批量操作、并发、异常处理等所有功能
- 可直接运行:所有代码适配 Python 3.12.10,SQL 可直接复制创建数据库表
- 注释完整:开发思路+逐行代码注释,新手零门槛上手
- 生产可用:最后提供单例工具类,直接用于项目开发