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() 习惯是避免“沉默失败”的第一道防线。