Pager Lifecycle Functions: Pinning Pages, Running Transactions, and Making Them Stick in SQLite

Hello, I’m Maneshwar. I’m working on FreeDevTools online currently building “one place for all dev tools, cheat codes, and TLDRs” — a free, open-source hub where developers can quickly find and use tools without any hassle of searching all over the internet.

In the last post, we walked through the pager’s entry points: opening databases, fetching pages, declaring write intent, and preparing journaling.

Today, we move into the control functions, the ones that manage page lifetimes, transaction boundaries, and commit vs rollback.

This is where the pager stops being a cache manager and fully reveals itself as SQLite’s transaction engine.

Pinning Pages: sqlite3PagerRef and sqlite3PagerUnref

Once a page is handed to the tree module, the pager must make sure that page doesn’t disappear underneath it.

That’s where reference counting comes in.

sqlite3PagerRef: Pinning a Page

This function increments the page’s reference count and marks the page as pinned

Pinned pages are untouchable:

  • They won’t be evicted
  • They won’t be recycled
  • They won’t be overwritten
    image

As long as the reference count is non-zero, the pager guarantees the page’s memory stays valid.

sqlite3PagerUnref: Letting Go

This function decrements the reference count.

When the count reaches zero the page becomes unpinned, eligible for reuse it may be placed on the cache freelist

A subtle but critical behavior happens here:

When all pages become unpinned:

  • The pager releases the shared lock on the database file
  • The Pager object returns to a neutral, idle state

image

This is how SQLite avoids holding locks longer than necessary, without explicit lock calls from higher layers.

Starting a Write Transaction: sqlite3PagerBegin

This function marks the beginning of an explicit write transaction.

What it does:

  • Acquires a reserved lock on the database file
  • Opens the rollback journal (unless the database is temporary)
  • Transitions the pager into write mode

If the database is already reserved for writing this function becomes a no-op

That’s important, because:

  • sqlite3PagerWrite may already have started an implicit write transaction
  • SQLite never duplicates work unnecessarily

There’s also an important option here the pager may acquire an exclusive lock immediately instead of waiting until actual writes begin

image

This choice affects concurrency and latency, and it’s entirely managed by the pager.

Commit Phase One: Making Data Durable

SQLite commits in two distinct phases.

The first is handled by:

sqlite3PagerCommitPhaseOne

This is the durability phase.

The pager:

  1. Increments the file-change-counter in the database header
  2. Syncs the rollback journal to disk
  3. Writes all dirty pages from the cache to the database file
  4. Syncs the database file itself

After this phase the database file contains the new data while journal still exists and recovery is still possible

At this point, the transaction is crash-safe, but not yet finalized.

image

Commit Phase Two: Declaring Victory

The second phase completes the commit:

sqlite3PagerCommitPhaseTwo

This function finalizes the journal file, deletes, truncates, or invalidates it

Once this happens:

  • Recovery is no longer needed
  • The transaction is officially complete
  • Locks can be safely downgraded

This split-phase design is what allows SQLite to survive crashes at any point in the commit sequence.

image

Rollback: Undo Without Failure

When something goes wrong or when the application asks for it the pager takes a different path.

sqlite3PagerRollback

This function:

  • Restores original page contents from the rollback journal
  • Reverts all in-memory pages
  • Finalizes the journal
  • Downgrades exclusive locks back to shared locks

Two important guarantees here:

  1. Rollback cannot fail
  2. The database is left in a consistent state

No matter how messy things got during execution, rollback always succeeds.

This is one of SQLite’s strongest correctness promises.
image

Savepoints: Nested Safety Nets

SQLite doesn’t treat transactions as flat structures.

Every SQL statement runs inside a savepoint, and applications can define their own as well.

The pager exposes two functions for this.

sqlite3PagerOpenSavepoint

This function:

  • Creates a new savepoint handler
  • Records the current rollback journal position
  • Captures the database state at that moment

Savepoints stack, multiple savepoints can coexist.

sqlite3PagerSavepoint: Release or Roll Back

This function does two very different things, depending on the request.

Savepoint Release

  • Destroys the savepoint handler
  • Keeps all changes made since the savepoint

Savepoint Rollback

  • Restores database state to the savepoint
  • Undoes all changes made after it
  • Deletes the rolled-back savepoint and all newer ones

This mechanism allows SQLite to roll back a single statement without aborting the entire transaction and without reopening files or resetting locks

Again, all handled by the pager.

image

The Bigger Picture

If you zoom out now, a pattern should be unmistakable.

The pager:

  • Owns page lifetimes
  • Owns transaction boundaries
  • Owns journaling
  • Owns durability
  • Owns recovery
  • Owns rollback

Higher layers simply request operations.

They never enforce correctness, they rely on it.

Wrapping Up the Pager Arc

Across the last few posts, we’ve gone from:

  • Journals
  • To transactions
  • To locks
  • To savepoints
  • And finally to the pager functions that glue it all together

My experiments and hands-on executions related to SQLite will live here: lovestaco/sqlite

References:

SQLite Database System: Design and Implementation. N.p.: Sibsankar Haldar, (n.d.).

FreeDevTools

👉 Check out: FreeDevTools

Any feedback or contributors are welcome!

It’s online, open-source, and ready for anyone to use.

⭐ Star it on GitHub: freedevtools

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post

Visual Components Work Ergonomics VC Ecosystem

Related Posts