liveBook · Manning

Database transaction

As explained in MongoDB 8.0 in Action, Third Edition

A transaction is a group of database operations committed as one unit or rolled back so that partial execution is not persisted.

A database transaction groups related reads and writes so they succeed together or fail together. If a travel booking reserves a flight but cannot reserve a hotel, aborting the transaction undoes the flight reservation rather than leaving a partial booking. section 8.0

In MongoDB, an operation on one document is already atomic: an insert, update, or delete completes fully or leaves that document unchanged. Use a multidocument transaction when one logical change must span documents or collections. WiredTiger uses optimistic concurrency control; conflicting writes can require a transaction to be retried. section 8.2 section 8.0

A practical transaction workflow is:

  • Start a session and transaction. Set appropriate read and write concerns; the mongosh example uses snapshot reads, majority writes, and a primary read preference. section 8.4.2
  • Perform the related operations in the transaction, then commit if they succeed or abort if one fails. section 8.4.2
  • Handle transient failures. In mongosh, the example explicitly retries labeled errors and ends each session; driver Callback APIs automate starting, committing, and retrying. section 8.4.2 section 8.4.3

Coordinated account update

An account change can update an account document and related customer documents while inserting a transaction record. Grouping those writes prevents a failed step from leaving only some records updated. The Node.js driver runs the operations inside a session.withTransaction callback. section 8.4.2 section 8.4.3

Listing 8.2 Executing a multidocument transaction with Node.js and Callback API
const { MongoClient } = require('mongodb')

// Replace with your actual connection string
const uri = "your_mongodb_connection_string"

async function run(accountId) {
  const client = new MongoClient(uri)

  try {
    await client.connect()
    const session = client.startSession()

    const transactionOptions = {
      readConcern: { level: 'snapshot' },
      writeConcern: { w: 'majority' },
      readPreference: 'primary'
    }

    await session.withTransaction(async () => {
      const accounts = client.db('sample_analytics').collection('accounts')
      const customers = client.db('sample_analytics').collection('customers')
      const transactions = client.db('sample_analytics').collection('transactions')
      const currentDate = new Date()

      const account = await accounts.findOne(
        { account_id: parseInt(accountId) },
        { session }
      )
      if (!account) throw new Error('Account not found')

      const accountsUpdateResult = await accounts.updateOne(
        { account_id: parseInt(accountId) },
        {
          $set: { limit: 12000, last_transaction_date: currentDate },
          $inc: { transaction_count: 1 }
        },
        { session }
      )

      const customersUpdateResult = await customers.updateMany(
        { accounts: { $in: [parseInt(accountId)] } },
        {
          $inc: { transaction_count: 1 },
          $set: { last_transaction_date: currentDate }
        },
        { session }
      )

      const transactionsInsertResult = await transactions.insertOne(
        {
          account_id: parseInt(accountId),
          transaction_count: account.transaction_count + 1,
          bucket_start_date: currentDate,
          bucket_end_date: currentDate,
          transactions: [
            {
              date: currentDate,
              amount: 1500,
              transaction_code: 'buy',
              symbol: 'amzn',
              price: '125.00',
              total: '187500.00'
            }
          ]
        },
        { session }
      )

      console.log("Transaction committed.")
      console.log("Accounts updated:", accountsUpdateResult.modifiedCount)
      console.log("Customers updated:", customersUpdateResult.modifiedCount)
      console.log("New transaction inserted:", transactionsInsertResult.insertedId)

    }, transactionOptions)

    session.endSession()
  } catch (error) {
    console.error("Transaction aborted due to error:", error)
  } finally {
    await client.close()
  }
}

// Get accountId from command line arguments
const accountId = process.argv[2]
if (!accountId) {
  console.error("Please provide an account ID as an argument.")
  process.exit(1)
}

run(accountId).catch(console.dir)

The Node.js listing shows the client session, transaction options, and withTransaction callback together. section 8.4.3

Do not use distributed transactions as a substitute for data modeling. Keeping related data together in embedded documents or arrays can avoid their performance cost. For transactions that remain necessary, use indexes, keep them short, plan error handling and retries, and account for added overhead across shards. The guidance recommends modifying no more than 1,000 documents per transaction and notes a default 60-second timeout. Some operations, including certain collection and index creation cases, are restricted within transactions. section 8.4.3 section 8.5

How MongoDB 8.0 in Action, Third Edition covers it

How deep it goes
Works through session setup, commit or abort, retries, and driver callbacks, then gives operational limits and restrictions.
Examples
Uses a flight-and-hotel booking and account, customer, and transaction-record updates implemented in mongosh and driver listings.
What it assumes
Starts with single-document atomicity before multidocument examples; runnable Node.js code requires a MongoDB connection string and driver installation.
What you can do after
Apply it via mongosh or MongoDB driver Callback APIs to commit coordinated writes and handle failures.
How it connects
Connects transactions to ACID properties, single-document atomicity, optimistic concurrency control, sharding, and schema design.

Also explained in

Compare how 14 books explain database transaction →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of MongoDB 8.0 in Action, Third Edition. The section links point to the parts of the book it draws on.