【问题标题】:How to find out root cause of transaction failure in Firestore?如何找出 Firestore 中交易失败的根本原因?
【发布时间】:2019-07-21 07:00:39
【问题描述】:

如果 Firestore 事务失败,它会抛出 FirestoreException,它只会说 “由于重试次数过多,事务被取消。”

没有根本原因或任何其他线索,即使我将退休人数设置为 1。

是否有可能找到根本原因?

【问题讨论】:

  • 这通常是因为您尝试修改的数据正在被其他客户端/进程在事务运行时修改。如果发生这种情况,Firestore 客户端将重试事务。但如果它反复发生,它就会放弃。除此之外,没有办法获得更多信息。
  • Firestore 无法设置事务的重试次数。在这种情况下,您实际设置了什么?
  • @DougStevenson 确实如此,至少在 Java Admin SDK 中如此。
  • 感谢 cmets。抱歉,如果我不清楚,我不是要调试特定案例,而是能够以编程方式确定根本原因(至少是最明显的原因,例如文档太大)
  • Frank 指出,所有客户端处理相同文档的并行度是罪魁祸首。在不了解您正在执行的实际事务以及并行度的情况下,没有什么可说的。

标签: java firebase google-cloud-firestore


【解决方案1】:

根据documentationFirestoreException的消息“Transaction was cancelled because too many retries.”只能在private void runTransactionAttempt下找到:

 private void maybeRetry() {
            if (attemptsRemaining > 0) {
              span.addAnnotation("retrying");
              runTransactionAttempt(
                  transactionCallback,
                  resultFuture,
                  new TransactionOptions(
                      attemptsRemaining, options.getExecutor(), transaction.getTransactionId()),
                  span);
            } else {
              span.setStatus(TOO_MANY_RETRIES_STATUS);
              rejectTransaction(
                  FirestoreException.serverRejected(
                      Status.ABORTED, "Transaction was cancelled because of too many retries."));
            }
          }

如您所见 - 您在尝试运行事务和/或批量写入时遇到重复异常。查看Firebase documentation 后,您可以看到导致交易失败的三个主要原因:

1.事务包含写操作之后的读操作。读 操作必须始终在任何写操作之前。

2. 事务读取的文档在 交易。在这种情况下,事务会自动再次运行。

3. 事务被重试有限次。交易 超过了 10 MiB 的最大请求大小。 事务大小取决于文档和索引条目的大小 由交易修改。对于删除操作,这包括 目标文档的大小和删除的索引条目的大小 响应操作。

为了调试问题,我强烈建议您使用以下资源进一步阅读 - 如果没有您的代码 sn-p,很难帮助您实施解决方案:

【讨论】:

  • 有没有办法记录 GRPC ApiException?也许那里的状态代码将有助于缩小哪些是实际问题。
  • @Andrew 你是指一般情况下还是在 OP 的情况下?
  • @Andrew One 只能捕获正在抛出的内容(或设置断点)。
  • @MartinZeitler 正确-尽管在原始问题的情况下,实际上是由于扩展了上传限制(正如他自己所提到的)。这就是我特意问的原因,但感谢您的回复!
【解决方案2】:

您应该检查您的 Firebase 控制台 Firestore 规则,如果允许编辑...创建新的、编辑权限。

service cloud.firestore {  
    match /databases/{database}/documents {
        // Anyone can read a product, only authorized
        // users can create or update. Deletes are not allowed.
        match /products/{productId} {
            allow read: if true;
            allow create, update: if request.auth.uid != null;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 2011-09-11
    • 2017-05-15
    • 2012-12-02
    • 2016-08-21
    • 1970-01-01
    相关资源
    最近更新 更多