0%

Chapter 7

Several Changes, One Outcome

When a Checkout Stops Halfway

A member asks to borrow the projector screen and repair kit together. Treating that request as two unrelated changes can leave a result nobody asked for.

Here is the proposed pair:

Loan IDItem IDMember IDCheckout date
70014172026-08-26
700259992026-08-26

The first row is valid. The second refers to member 999, who does not exist. Suppose a program stores and finishes the first row before it tries the second:

Proposed loans: [(7001, 4, 17, '2026-08-26'), (7002, 5, 999, '2026-08-26')]
Second loan: rejected by the missing-member rule
New loan IDs after reopening: [7001]
Wanted new loan IDs: []

The database correctly refused the invalid statement. It did not know that the two statements represented one request. Loan 7001 remains, so the catalog records only half of the requested checkout.

For this operation, success means both new rows are stored. Failure means neither new row is stored. This all-or-nothing property is called atomicity. A database groups changes so they reach one outcome together.

Atomicity does not mean that every two statements everywhere must be grouped. It follows the meaning of the operation. Two independent members checking out unrelated items could be separate outcomes. These two rows are one kit request, so a partial prefix is not useful success.

What went wrong in the observed two-item checkout?

Python needs a clear success point and a clear failure path. Start with the successful half before changing how failures are resolved.