Lesson 6 of 12

How a B-tree Splits Without Stopping the World: Lehman-Yao in PostgreSQL

Applies to PostgreSQL 13–17 Last reviewed Jun 2026 Grounded in source

The one thing to understand first

A B-tree index is constantly being modified by many sessions at once, yet a reader almost never has to wait for a writer. PostgreSQL pulls this off with a 1981 idea called the Lehman-Yao B-link tree: every page carries a high key (the largest key it is allowed to hold) and a right-link to its sibling. Those two things let a search that lands on a page just after a concurrent split simply walk right to find its key, instead of locking the whole path. The whole concurrency story is one sentence: readers hold one page lock at a time and recover from races by following right-links.

The shape of a page

In src/backend/access/nbtree/, every B-tree page ends with a BTPageOpaqueData struct (see nbtree.h) holding btpo_prev and btpo_next — the left and right sibling pointers at the same level. On every page except the rightmost on its level, the first item is the high key: an upper bound such that every key on the page is <= the high key. Internal pages additionally hold downlinks (block numbers) to children. Leaf pages hold the actual indexed values plus a TID (heap ctid) pointing at the table row.

A search that never lock-couples

Descent lives in nbtsearch.c. _bt_search() walks from the root down, and at each level _bt_binsrch() binary-searches the page for the child to follow. The crucial trick is _bt_moveright(): after locking a page, the code checks the high key. If the key it is looking for is greater than the high key, that means a split moved the target onto the right sibling after we read the parent’s downlink — so the code follows btpo_next to the right and retries, rather than restarting from the top. Because a reader only ever holds one page lock at a time (no lock-coupling), writers are rarely blocked.

This is a Pro lesson

Get every Learning Pathway and cookbook recipe — grounded in PostgreSQL source code, with diagnostics, fixes, and prevention for each topic.

Continue this lesson to learn:

  • What happens on insert
  • Two space-savers worth knowing
  • Layer 3 — Look inside a real B-tree with pageinspect
  • Layer 4 — The levers this hands you
  • Layer 5 — What an Oracle DBA should expect vs what they get
  • Key takeaway
  • All 36 Learning Pathway lessons
  • 170+ cookbook recipes
  • Source-grounded diagnostics & fixes

Secure checkout Cancel anytime Source-grounded

Was this helpful?

← Back to 05 — The Engine Room: How PostgreSQL Actually Executes