Skip to content

Race Condition in Multiplexed Session #2368

@alkatrivedi

Description

@alkatrivedi

Transaction gets assigned to the session as per this ref.

Issue:
In a multiplexed architecture, a single session is reused to handle multiple transactions, creating a one-to-many relationship. While efficient, this model introduces a critical problem in a multithreaded environment.

The core issue is a race condition. When multiple threads operate in parallel, they share the same session object. As each thread initiates a new transaction, it overwrites a common transaction field (txn) within that shared session object.

Consequently, operations from one thread can be mistakenly executed within the context of a transaction started by a different thread. This leads to severe errors, including:

Incorrect transaction execution: Logic intended for one transaction is applied to another.

Erroneous commits: Data is committed to the database under the wrong transaction, leading to data corruption and inconsistent state within the client.

Steps to reproduce:
Run below script on multiple threads in parallel

await database.runTransactionAsync(async tx => {
  const [rows] = await tx.run('SELECT * FROM Singers');
  rows.forEach(row => {
    const json = row.toJSON();
    console.log(`SingerId: ${json.SingerId}, FullName: ${json.FullName}`);
  });
  const id = Math.floor(Math.random() * 10000) + 1;
  const name = randomUUID();
  tx.upsert('Singers', [{SingerId: id, FirstName: name}]);
  await tx.commit();
  console.log('transaction done.');
}

cc: @surbhigarg92

Metadata

Metadata

Assignees

Labels

api: spannerIssues related to the googleapis/nodejs-spanner API.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions