The life of a query
Every station a statement visits inside Firebird, from the client to the committed record version and back — the same journey the particles make in the city, in plain text.
← back to the cityUse Tab / Shift+Tab or arrow keys to move between stations. Everything on this page works without a mouse, a canvas, or JavaScript.
-
Client application REMOTE
The statement leaves your program through the client library. The remote layer packages it for the wire — TCP/IP to another machine, or XNET shared memory on the same one.
-
Y-valve dispatch Y-VALVE
The Y-valve looks at the connection string and routes the attachment to the right provider: the network redirector, or the embedded in-process engine. Every call in and every result out passes through this gate.
-
Lexer DSQL
The lexical analyzer splits the SQL text into tokens — keywords, identifiers, literals, operators.
-
Parser DSQL
The parser builds a syntax tree from the token stream, checking the statement is well-formed SQL.
-
BLR generation DSQL
The code generator emits BLR — Binary Language Representation, the engine's native language. From here on the statement no longer speaks SQL. Stored procedures and triggers are kept in BLR form too.
-
Security check SCL
The attachment was authenticated against the security database when it connected; now SQL privileges and ACLs are enforced on every object the statement touches.
-
Compile & optimize CMP + MET
The compiler turns BLR into an executable request tree, resolving tables and columns against the metadata subsystem (the RDB$ system tables). The optimizer picks indexes and join order from selectivity and cardinality estimates.
-
Execution EXE
The heart of JRD interprets the request tree, pulling rows through record streams and coordinating every subsystem below.
-
Index walk — when one fits BTR
If the optimizer chose an index, the B-tree subsystem walks prefix-compressed keys down to matching record numbers instead of scanning the table.
-
Sort — when no index gives the order SORT
ORDER BY, GROUP BY and DISTINCT without a helpful index go through the external merge sort: sorted runs in memory, spilled and merged through temporary files when they outgrow it.
-
Page cache CCH
Every page the engine touches goes through the shared buffer cache. A hit costs nothing; a miss means physical I/O against the database file — and evicting the least-recently-used buffer if the cache is full.
-
The database file PIO
The physical I/O layer reads and writes pages of the single database file. There is no write-ahead log: careful write ordering keeps the on-disk structure consistent at every instant — a page is never written before the pages it points to exist.
-
Locking — writers only LOCK
Before modifying, the engine takes a lock in the shared-memory lock table that coordinates all attachments (and, in Classic mode, all processes). Contending writers queue; the deadlock scanner picks a victim when two queues form a cycle.
-
A new record version VIO
An UPDATE never overwrites the row. It writes a new version and chains the old one behind it as a backward delta. Readers walk the chain to the version their transaction snapshot may see — readers never block writers. Old versions below the Oldest Interesting Transaction become garbage for cooperative GC or the sweep.
-
Commit TRA
The transaction's state bits flip on a Transaction Inventory Page. No redo log, no undo log — the version chains and the TIP are the whole story. The new version is now the committed truth.
-
Results sail home REMOTE
Rows are batched back through the Y-valve and the wire protocol to the client that asked. In the city, this is the green particle returning to the harbor.
Part of FBSimCity — an explorable city of Firebird internals. Subsystem structure from Conceptual Architecture for Firebird (Chan & Yashkir). FBSimCity is an independent educational project, not affiliated with or endorsed by the Firebird Project. Firebird® is a registered trademark of the Firebird Foundation Incorporated.