Firebase事务是否兼容所有写入操作?含Cloud Functions及原子性疑问
Firestore事务与并发写入的原子性问题解答
客户端事务的原子性
你客户端的写入操作具备完整的原子性。Firestore的runTransaction机制本身就提供原子性保障:
- 事务内的读写操作会基于目标文档的最新快照执行
- 如果事务执行期间,文档被其他操作(包括Cloud Functions的普通更新)修改,事务会自动重试,直到逻辑成功完成或达到系统重试上限
- 整个事务要么全部执行成功,要么全部失败,不会出现部分更新的异常情况
你的Dart代码逻辑(仅当isAcar为false时更新为true)会被事务完整原子化执行,不会因并发写入导致逻辑失效。
Cloud Functions是否需要改用事务?
不需要。原因如下:
- Firestore单个文档的普通
update操作本身是原子的,但它不具备事务的“读-改-写”并发冲突处理能力 - 但客户端的事务已经通过乐观锁机制处理了并发问题:当Cloud Functions的
update与客户端事务同时操作同一文档时,客户端事务会检测到文档版本变更,自动重试执行逻辑,确保最终结果符合你设定的条件(只有isAcar为false时才更新)
举个并发场景的例子:
- 客户端事务读取到
isAcar为false,准备执行更新 - 同时Cloud Functions的
update将isAcar设为true - 客户端事务提交时发现文档版本已改变,自动重试:重新读取文档后发现
isAcar为true,便不会执行更新,逻辑依然正确
附原代码格式化
Cloud Functions代码
exports.onUserStatusChanged = functions.database.ref('/users/{uid}').onUpdate( async (change, context) => { const eventStatus = change.after.val(); const userStatusFirestoreRef = firestore.doc(`users/${context.params.uid}`); return userStatusFirestoreRef.update(eventStatus); });
客户端Dart事务代码
myFunction(){ DocumentReference doc = FirebaseFirestore.instance.collection("users").doc('123'); FirebaseFirestore.instance.runTransaction((transaction) async { DocumentSnapshot docVal = await transaction.get(doc); if (docVal.get('isAcar') == false) { transaction.update(doc, { 'isAcar': true, }); } }); }
内容的提问来源于stack exchange,提问作者Mohammed Hamdan
相关产品推荐
相关产品推荐

