Skip to content

Spanner: executeUpdate() and batchUpdate() could cause AbortedException when using TransactionManager #5951

@olavloite

Description

@olavloite

When using a Cloud Spanner TransactionManager to execute a read/write transaction, TransactionContext#executeUpdate(Statement) and TransactionContext#batchUpdate(Statement) do not handle an aborted transaction correctly. If the following transaction is executed:

    DatabaseClient client =
        spanner.getDatabaseClient(DatabaseId.of(PROJECT_ID, INSTANCE_ID, DATABASE_ID));
    try (TransactionManager manager = client.transactionManager()) {
      TransactionContext txn = manager.begin();
      while (true) {
        try {
          ...
          // Transaction has been aborted by Cloud Spanner before the following statement.
          long updateCount = txn.executeUpdate("UPDATE FOO SET BAR=1 WHERE ID=1");
          manager.commit();
          break;
        } catch (AbortedException e) {
          Thread.sleep(e.getRetryDelayInMillis() / 1000);
          // This line will throw an IllegalStateException with message
          // 'resetForRetry can only be called if the previous attempt aborted'
          // because the executeUpdate(...) method does not inform the transaction
          // manager that the transaction aborted.
          txn = manager.resetForRetry();
        }
      }
    }

Related to #4166 and #4939. These issues were fixed, but only when using a TransactionRunner, and not when using a TransactionManager.

Metadata

Metadata

Assignees

Labels

api: spannerIssues related to the Spanner API.triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions