iOS发布模式下触发sqflite错误:cannot commit - no transaction is active
iOS发布模式下sqflite报错:
cannot commit - no transaction is active 排查与解决 错误信息
flutter: error DatabaseException(Error Domain=SqfliteDarwinDatabase Code=1 "cannot commit - no transaction is active" UserInfo={NSLocalizedDescription=cannot commit - no transaction is active}) sql 'COMMIT' args [] during open, closing... [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DatabaseException(Error Domain=SqfliteDarwinDatabase Code=1 "cannot commit - no transaction is active" UserInfo={NSLocalizedDescription=cannot commit - no transaction is active}) sql 'COMMIT' args []
问题场景
- 仅在iOS发布模式下启动应用时触发该错误
- 应用启动后黑屏,但会正常请求相机权限
核心代码实现
获取数据库实例 getDBInstance
Future<Database> getDBInstance({BuildContext? context}) async { debugPrint('getting db instance'); if (database == null) { debugPrint('db is null'); Database db; if (Platform.isWindows) { sqfliteFfiInit(); var databaseFactory = databaseFactoryFfi; db = await databaseFactory.openDatabase("cashway.db", options: OpenDatabaseOptions( version: 1, onCreate: onCreate, onUpgrade: onUpgrade)); } else { String databasesPath = await getDatabasesPath(); String dbPath = join(databasesPath, 'cashway.db'); //the last printed output debugPrint('opening db'); db = await openDatabase(dbPath, version: 1, onCreate: onCreate, onUpgrade: onUpgrade); } database = db; return db; } else { Database db = database!; return db; } }
数据库创建回调 onCreate
void onCreate(Database database, int version) async { debugPrint('on create'); for (MigrationCallback callback in migrations) { debugPrint('doin migration'); await callback(database); } resetDatabase(); }
应用入口 main
void main() async { WidgetsFlutterBinding.ensureInitialized(); await getDBInstance(); AppProvider appProvider = await AppProvider.getInstance(); runApp(MultiProvider( providers: [ChangeNotifierProvider(create: (_) => appProvider)], child: const App())); }
数据库重置方法 resetDatabase
Future<void> resetDatabase(database) async { debugPrint('resetting'); database.delete("payments", where: "id>0"); database.delete("accounts", where: "id>0"); database.delete("categories", where: "id>0"); debugPrint('removed all entries'); await database.insert("accounts", { "name": "Наличные", "icon": Icons.wallet.codePoint, "color": Colors.teal.value, "isDefault": 1 }); }
排查与解决思路
1. 核心问题定位
错误提示cannot commit - no transaction is active,本质是代码中存在未等待异步操作完成就触发事务提交的情况:
resetDatabase中的3个delete操作未加await,导致这些异步操作在后台执行时,sqflite的隐式事务逻辑出现异常onCreate调用resetDatabase时也未加await,导致数据库创建流程提前结束,触发事务提交错误
2. 修复步骤
修复resetDatabase中的异步等待
给所有数据库操作添加await,确保操作顺序执行:
Future<void> resetDatabase(database) async { debugPrint('resetting'); await database.delete("payments", where: "id>0"); await database.delete("accounts", where: "id>0"); await database.delete("categories", where: "id>0"); debugPrint('removed all entries'); await database.insert("accounts", { "name": "Наличные", "icon": Icons.wallet.codePoint, "color": Colors.teal.value, "isDefault": 1 }); }
修复onCreate中的异步等待
确保resetDatabase执行完成后再结束创建流程:
void onCreate(Database database, int version) async { debugPrint('on create'); for (MigrationCallback callback in migrations) { debugPrint('doin migration'); await callback(database); } await resetDatabase(database); }
3. 额外验证点
- 检查
migrations中的所有迁移操作,确保异步数据库操作都添加了await - 用
flutter run --release命令重新验证iOS发布模式下的运行情况 - 确认数据库单例的访问逻辑,避免多线程同时触发数据库操作(sqflite为单线程设计,异步操作需保证顺序)
内容的提问来源于stack exchange,提问作者Vassily
相关产品推荐
相关产品推荐

