Firestore事务后立即读取数据不一致的原因排查
在Flutter中使用Cloud Firestore Native模式时,遇到一致性异常问题:事务成功更新一个文档并创建另一个文档后,立即读取这两个文档,得到的却是更新前的旧快照,以及新创建文档exists==false的结果。
已知Firestore Native模式保证强一致性,理论上事务提交完成后,后续读取应获取最新数据。但在事务和读取之间加入1秒延迟后,就能稳定拿到事务完成后的正确文档版本。
已确认:
- 代码中是等待事务完全完成后才执行读取操作
- Cloud Functions第一代
onCreate/onUpdate触发器的实际执行未干扰结果(比如未删除新创建的文档)
不带触发器的简单测试用例表现符合预期,代码如下:
final ref1 = FirebaseFirestore.instance.doc('Parents/parent1'); final ref2 = FirebaseFirestore.instance.doc('Children/child1'); await FirebaseFirestore.instance.runTransaction((transaction) async { final doc1 = await transaction.get(ref1); final doc2data = { 'value': doc1.data()!['value'], }; transaction.update(ref1, { 'children': FieldValue.arrayUnion(['child1']), }); transaction.set(ref2, doc2data); }); final doc1 = await ref1.get(); debugPrint('doc1:children: ${doc1.data()?['children']}'); final doc2 = await ref2.get(); debugPrint('doc2.exists: ${doc2.exists}');
测试用例的预期输出:
flutter: doc1:children: [child1] flutter: doc2.exists: true
这种“延迟一致性”并非Firestore强一致性机制失效,核心原因和客户端缓存逻辑、服务器数据同步窗口、Cloud Functions触发器的异步特性相关,具体拆解:
客户端本地缓存的 stale read
Firestore Native客户端会维护本地缓存,事务提交后,客户端可能还未完成与服务器的最新数据同步,此时立即读取会命中本地旧缓存。加入延迟后,缓存同步完成,就能拿到最新数据。而不带触发器的测试用例正常,说明单纯的事务+本地读取不会触发该问题,需结合触发器的影响判断。Cloud Functions触发器的异步执行窗口
第一代Cloud Functions的onCreate/onUpdate触发器是异步触发的,事务提交后,Firestore需要先将数据同步到全局存储节点,再触发函数执行。这个同步过程存在极短的时间窗口,若客户端读取刚好发生在窗口内,就可能读取到未完全同步的旧数据。事务提交后的全局复制延迟
事务的await仅代表客户端收到了服务器的提交成功响应,但服务器端还需完成数据的全局复制与索引更新。此时客户端立即读取若访问的是未完成复制的节点,就会拿到旧数据。延迟1秒后,全局复制完成,读取结果恢复正常。
内容的提问来源于stack exchange,提问作者Stephen Hu

