
aiosqlite 的异步操作需显式调用 commit() 才能将 insert 等修改写入磁盘,否则事务自动回滚,导致“无错误但数据未保存”。
aiosqlite 的异步操作需显式调用 commit() 才能将 insert 等修改写入磁盘,否则事务自动回滚,导致“无错误但数据未保存”。
在使用 aiosqlite 进行数据库写入时,一个常见却极易被忽视的关键点是:所有修改类操作(如 INSERT、UPDATE、DELETE)必须显式提交事务,否则即使执行成功,数据也不会真正保存到数据库文件中。这与同步的 sqlite3 模块默认启用 autocommit 模式(部分场景下)不同,aiosqlite 默认遵循标准 SQLite 事务行为——即每个 execute() 都运行在隐式事务中,若未调用 commit(),连接关闭时事务自动回滚。
你当前的 add_user 方法存在两个核心问题:
- 缺少 commit() 调用:await cursor.execute(...) 仅执行语句,但未提交;
- 连接未正确管理:aiosql.connect() 返回的是连接对象,而 con.cursor() 创建游标后,仍需通过 con.commit() 提交;此外,直接使用 con.cursor() 并非必需,推荐直接调用 con.execute()(它内部会处理游标),更简洁安全。
✅ 正确写法如下(已优化结构与健壮性):
async def add_user(self, uid: int) -> None:
"""向 users 表插入新用户,确保事务提交"""
await self.start() # 确保表已创建
async with aiosql.connect(self.path) as con:
await con.execute(
"INSERT OR IGNORE INTO users(user_telegram_id, status) VALUES(?, ?)",
(uid, "member")
)
await con.commit() # ✅ 关键:必须显式提交!⚠️ 注意事项:
- INSERT OR IGNORE 可防止重复插入同一 user_telegram_id 时报错(因主键冲突);
- await con.commit() 必须在 async with 块内调用,且在连接关闭前;
- 不要混用 cursor.execute() 和 con.execute();优先使用 con.execute(),它更符合 aiosqlite 最佳实践;
- 若需批量插入,可使用 con.executemany() + 单次 commit() 提升性能;
- 建议在 start() 方法中也添加 await con.commit()(尽管 CREATE TABLE IF NOT EXISTS 是 DDL,通常自动提交,但显式提交更统一、可读)。
? 总结:aiosqlite 不是“开箱即用”的免提交方案。它的异步优势不改变 SQLite 的事务本质——没有 commit,就没有持久化。养成每次写操作后调用 await con.commit() 的习惯,是避免“静默失败”的第一道防线。

















