
Firestore 点-in-time 恢复(PITR)要求 readTime 必须严格对齐到整分钟(秒和纳秒均为 0),否则会触发“Invalid transaction”错误;即使时间在保留窗口内,非整分钟时间戳也会被拒绝。
firestore 点-in-time 恢复(pitr)要求 `readtime` 必须严格对齐到整分钟(秒和纳秒均为 0),否则会触发“invalid transaction”错误;即使时间在保留窗口内,非整分钟时间戳也会被拒绝。
Firestore 的 PITR 功能允许开发者以只读事务方式查询文档在历史某一时刻的状态,但其时间精度约束非常严格——readTime 必须是精确到分钟的时间戳(即秒数为 60 的整数倍,纳秒部分必须为 0)。你提供的原始时间戳 { _seconds: 1694362757, _nanoseconds: 397127000 } 对应 2023-09-10 16:19:17.397127,秒级为 17,纳秒非零,因此不满足要求,导致 SDK 抛出 Invalid transaction 错误。
✅ 正确做法是将时间向下取整至最近的整分钟(注意:不可向上取整,否则可能超出数据存在时间点):
const originalTimestamp = new Timestamp(1694362757, 397127000); // 16:19:17.397...
// 转换为毫秒,截断到分钟级别
const ms = originalTimestamp.toDate().getTime();
const roundedMs = Math.floor(ms / (60 * 1000)) * (60 * 1000);
const readTime = new Timestamp(
Math.floor(roundedMs / 1000),
0 // 纳秒必须为 0
);
const ref = db.collection('rentals').doc('q5MsBad7ZKM9jP5FbZbJ');
const doc = await db.runTransaction(
transaction => transaction.get(ref),
{ readOnly: true, readTime }
);
⚠️ 注意事项:
- 时间必须在 PITR 保留窗口内(默认 7 天),且不得早于 earliestVersionTime(可通过 gcloud firestore databases describe 查询);
- 整分钟规则是硬性校验,SDK 不会自动四舍五入或截断;
- 若目标时刻恰好处于分钟边界但纳秒非零(如 16:19:00.000000001),仍需手动归零纳秒;
- 使用 new Date().toISOString() 验证:合法时间戳格式应为 YYYY-MM-DDTHH:MM:00Z(无秒后小数)。
总结:PITR 不是“任意时间点快照”,而是基于分钟粒度的版本索引机制。确保 readTime 的 _seconds 是 60 的倍数、_nanoseconds === 0,是成功调用的前提。调试时建议先打印 readTime.toDate().toISOString() 确认格式合规。










