Flutter & Firestore技术疑问:在事务函数内添加数据是否可行?
Firestore事务内添加数据的合理性分析及代码修正
当前代码的关键bug
你现在的写法存在致命问题:创建用户文档的set操作没有通过事务对象执行,而是直接调用了Firestore实例的方法。这意味着用户文档的写入不在事务的原子性管控范围内——如果后续更新memberCount时事务失败回滚,用户文档已经被创建成功,但memberCount没增加;反过来,如果用户文档写入失败,事务却可能已经完成了memberCount的更新,最终导致数据不一致。
事务内添加数据是否合理?
完全合理,但必须遵循Firestore事务的核心规则:所有需要保证原子性的操作,都要通过事务对象(代码里的transaction参数)执行,不能直接用db实例操作。这样事务才能保证所有操作要么全部成功提交,要么全部失败回滚,完美满足你“用户文档创建成功后再增加memberCount”的需求。
修正后的代码
把创建用户文档的逻辑改成通过transaction.set()执行,将其纳入事务管控:
var db = FirebaseFirestore.instance; await db.runTransaction((transaction) async { final memberCountDoc = db.collection('variables').doc('memberCount'); final snapshot = await transaction.get(memberCountDoc); int newMemberCount = snapshot.get('value') + 1; Map<String, dynamic> userdata = { 'sequence': newMemberCount, 'enrollTime': DateTime.now().toUtc(), }; var user = FirebaseAuth.instance.currentUser; // 改用transaction.set,将用户文档写入纳入事务原子性管控 await transaction.set(db.collection('users').doc(user!.uid), userdata); transaction.update(memberCountDoc, {'value': newMemberCount}); return newMemberCount; }).then( (value) => print('Now you have $value members!'), onError: (e) => print(e), );
关于效率问题
Firestore事务的性能开销主要来自冲突重试(当多个事务同时修改memberCount时,系统会自动重试失败的事务),但对于普通会员注册场景,这种开销完全可以忽略。只有当你面临每秒数百次以上的并发注册时,才需要考虑用分布式计数器拆分memberCount来优化性能,绝大多数业务场景下,事务的效率足够用。
内容的提问来源于stack exchange,提问作者whaaaaazup
相关产品推荐
相关产品推荐

