Module 5: Modifying Data ⏱ 18 min

Transactions and ACID

By the end of this lesson you will be able to:
  • Group several modifications into a transaction with BEGIN, COMMIT, and ROLLBACK
  • Explain the four ACID guarantees a transaction provides
  • Decide when a batch of changes must be all-or-nothing

Suppose you reassign an employee from Sales to Marketing. At minimum that is one UPDATE. But a real move might be several statements: change the department, rewrite a budget line, close one project and open another. If the connection drops after the first statement, the database is left half-moved — inconsistent, with no clean way to know how far it got.

A transaction bundles statements into a single unit that is all-or-nothing. Either every statement inside it takes effect, or none of them do. That guarantee is the difference between a database and a pile of files: when something goes wrong halfway through, you can put the data back exactly as it was.

flowchart TD
  B["BEGIN"] --> S1["statement 1"] --> S2["statement 2"] --> E{"how it ends"}
  E -->|"COMMIT"| C["both changes saved"]
  E -->|"ROLLBACK"| R["both changes undone"]
  style C fill:#0e7490,color:#fff
  style R fill:#b45309,color:#fff
BEGIN opens a transaction; COMMIT keeps every change, ROLLBACK discards every change.

BEGIN, COMMIT, and ROLLBACK

A transaction has a clear shape: open it with BEGIN, run your statements, then end it with either COMMIT to keep the changes or ROLLBACK to throw them away:

BEGIN;
UPDATE employees SET department_id = 2 WHERE id = 8;
UPDATE employees SET department_id = 2 WHERE id = 7;
COMMIT;

Until COMMIT runs, those two updates are provisional — visible only inside this transaction. COMMIT makes them permanent and visible to everyone else; ROLLBACK would undo both as if they never happened. The two statements are now a single decision: they land together or not at all.

Move two employees to Marketing in one transaction, then confirm both moved.
BEGIN;
UPDATE employees SET department_id = 2 WHERE id = 8;
UPDATE employees SET department_id = 2 WHERE id = 7;
COMMIT;

SELECT name, department_id FROM employees WHERE id IN (7, 8) ORDER BY id;

The four guarantees: ACID

A transaction's safety rests on four properties, remembered by the initials ACID. Atomicity means all-or-nothing: the statements either all take effect or none do, so a partial transfer can never leave money deducted from one place but never added to another. Consistency means the database moves from one valid state to another — every constraint and key still holds when the transaction finishes. Isolation means concurrent transactions behave as though they ran one at a time, so two people editing the same row cannot corrupt each other's work. Durability means once COMMIT returns, the change survives even a power cut.

flowchart LR
  A["Atomic<br/>all or nothing"] --> T["ACID"]
  C["Consistent<br/>rules hold"] --> T
  I["Isolated<br/>concurrent safe"] --> T
  D["Durable<br/>survives crashes"] --> T
  style T fill:#0e7490,color:#fff
The four ACID properties a transaction guarantees.

ROLLBACK is an undo button

ROLLBACK discards every change the transaction made, restoring the database to the state it was in at the BEGIN. It is how you abandon a batch you no longer trust — a validation check failed, a total came out wrong, the user pressed cancel.

Run the statements inside the transaction first, inspect the results, and if they are wrong issue ROLLBACK rather than trying to hand-write corrective updates. Undoing a whole transaction is always cleaner than reversing its statements one by one, because there is nothing to forget and nothing to get out of order.

Delete a project inside a transaction, then ROLLBACK — it is still there.
BEGIN;
DELETE FROM projects WHERE id = 7;
ROLLBACK;

SELECT name FROM projects WHERE id = 7;
flowchart LR
  S1["step 1<br/>debit account"] --> X{"step 2 ok?"}
  X -->|"fails"| BAD["inconsistent state"]
  X -->|"in a txn"| SAFE["rolled back<br/>both undone"]
  style BAD fill:#b45309,color:#fff
  style SAFE fill:#0e7490,color:#fff
Without a transaction, a failure halfway through leaves the data inconsistent. In a transaction, a failure rolls everything back.

Durability and the default of autocommit

Outside any transaction, SQLite runs in autocommit mode: each statement is its own tiny transaction, committed the instant it finishes. That is convenient for one-off changes, which is why the earlier lessons never needed BEGIN. The moment your changes must hang together, you switch off autocommit by opening an explicit transaction. COMMIT is also the point where durability is honoured — the database writes the changes to durable storage before it tells you it succeeded, so a crash a millisecond later cannot lose them.

A committed raise: the change persists past COMMIT and shows in the next read.
BEGIN;
UPDATE employees SET salary = salary + 10000 WHERE department_id = 5;
COMMIT;

SELECT name, salary FROM employees WHERE department_id = 5 ORDER BY id;
Exercise

In one transaction, move Hana Suzuki (id 8) and Gustav Berg (id 7) to the Marketing department (department_id = 2). Wrap both updates in BEGIN and COMMIT so they land together.

BEGIN;
-- update id 8
-- update id 7
COMMIT;
Exercise

Which ACID property guarantees that all changes in a transaction happen together, or none of them do?

Exercise

Start a transaction, delete the Gamma Helpdesk project (id 7), then ROLLBACK so the deletion is undone. The project must still be present afterward.

BEGIN;
-- delete project 7
-- then undo it
;
Exercise

Create a new department 'Data' (id 6, city 'Bergen') and immediately its first employee 'Sam Idris' (id 16, department_id 6, role 'Data Engineer', salary 800000). Do both in one transaction so the parent and child commit together.

BEGIN;
-- insert the department
-- insert its first employee
COMMIT;
Exercise

Transfer skill: in one transaction, give every employee hired before 2020 (hired_on < '2020-01-01') a raise of 100000. Combine a filter, an update, and a transaction.

BEGIN;
-- update everyone hired before 2020
COMMIT;

Recap

  • A transaction groups statements into an all-or-nothing unit via BEGIN, COMMIT, and ROLLBACK.
  • COMMIT keeps every change and makes it durable; ROLLBACK undoes them all.
  • ACID is the four guarantees: Atomic (all or nothing), Consistent (rules hold), Isolated (concurrent safe), Durable (survives crashes).
  • Outside a transaction SQLite runs in autocommit — each statement commits on its own.
  • Every BEGIN must be paired with exactly one COMMIT or ROLLBACK.

Next you will see how foreign keys keep related tables consistent, so a transaction's guarantees are reinforced by rules the database itself enforces.

Checkpoint quiz

What does ROLLBACK do to the changes made inside a transaction?

Which best describes the I in ACID?

Go deeper — technical resources