Database Header Page - type 0x01

<< Standard database page header | Firebird Internals | Page Inventory Page - type 0x02 >>

Database Header Page - type 0x01

The first page of the first file of a Firebird database is a very important page. It holds data that describes the database, where its other files are to be found, shadow file names, database page size, ODS version and so on. On startup, the Firebird engine reads the first part (1,024 bytes) of the first page in the first file of the database and runs a number of checks to ensure that the file is actually a database and so on. If the database is multi-file, then each file will have a header page of its own.

The C code representation of the database header page is:

 struct header_page
 {
     pag hdr_header;
     USHORT hdr_page_size;
     USHORT hdr_ods_version;
     SLONG hdr_Pages;
     ULONG hdr_next_page;
     SLONG hdr_oldest_transaction;
     SLONG hdr_oldest_active;
     SLONG hdr_next_transaction;
     USHORT hdr_sequence;
     USHORT hdr_flags;
     SLONG hdr_creation_date[2];
     SLONG hdr_attachment_id;
     SLONG hdr_shadow_count;
     SSHORT hdr_implementation;
     USHORT hdr_ods_minor;
     USHORT hdr_ods_minor_original;
     USHORT hdr_end;
     ULONG hdr_page_buffers;
     SLONG hdr_bumped_transaction;
     SLONG hdr_oldest_snapshot;
     SLONG hdr_backup_pages;
     SLONG hdr_misc[3];
     UCHAR hdr_data[1];
 };

back to top of page

Hdr_header: The database header page has a standard page header, as do all pages.

Hdr_page_size: Two bytes, unsigned. Bytes 0x10 - 0x11 on the page. This is the page size, in bytes, for each and every page in the database.

Hds_ods_version: Two bytes, unsigned. Bytes 0x12 and 0x13 on the page. The ODS major version for the database. The format of this word is the ODS major version ANDed with the Firebird flag of 0x8000. In the example below, the value is 0x800b for ODS version 11. The minor ODS version is held elsewhere in the header page - see hdr_ods_minor below.

Hdr_pages: Four bytes, signed. Bytes 0x14 - 0x17 on the page. This is the page number of the first pointer page for the table named RDB$PAGES. When this location is known, the database engine uses it to determine the locations of all other metadata pages in the database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_next_page: Four bytes, unsigned. Bytes 0x18 - 0x1b on the page. The page number of the header page in the next file of the database - if this is a multi-file database. Zero otherwise.

Hdr_oldest_transaction: Four bytes, signed. Bytes 0x1c - 0x1f on the page. The transaction ID of the oldest active (ie, uncommitted - but may be in limbo or rolled back) transaction against this database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_oldest_active: Four bytes, signed. Bytes 0x20 - 0x23 on the page. The transaction ID of the oldest active transaction against this database, when any active transaction started. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_next_transaction: Four bytes, signed. Bytes 0x24 - 0x27 on the page. The transaction ID that will be assigned to the next transaction against this database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_sequence: Two bytes, unsigned. Bytes 0x28 and 0x29 on the page. The sequence number of this file within the database.

back to top of page

Hdr_flags: Two bytes, unsigned. Bytes 0x2a and 0x2b on the page. The database flags. The bits in the flag bytes are used as follows:

Flag nameFlag valueDescription
hdr_active_shadow0x01 (bit 0)This file is an active shadow file.
hdr_force_write0x02 (bit 1)The database is in forced writes mode.
Unused0x04 (bit 2)Was previously for short term journalling, no longer used.
Unused0x08 (bit 3)Was previously for long term journalling, no longer used.
hdr_no_checksums0x10 (bit 4)Don't calculate checksums.
hdr_no_reserve0x20 (bit 5)Don'r reserve space for record versions in pages.
Unused0x40 (bit 6)Was used to indicate that the shared cache file was disabled.
hdr_shutdown_mask
(bit one of two)
0x1080 (bits 7 and 12)Used with bit 12 (see below) to indicate the database shutdown mode.
hdr_sql_dialect_30x100 (bit 8)If set, the database is using SQL dialect 3.
hdr_read_only0x200 (bit 9)Database is in read only mode.
hdr_backup_mask0xC00 (bits 10 and 11)Indicates the current backup mode.
hdr_shutdown_mask
(bit two of two)
0x1080 (bits 7 and 12)Used with bit 7 (see above) to indicate the database shutdown mode.

The final two database flags use a pair of bits to indicate various states of backup and shutdown.

Hdr_backup_mask: These two bits determine the current database backup mode, as follows:

Flag valueDescription
0x00 (Both bits zero)Database is not in backup mode. User changes are written directly to the database files.
0x400The database is running in backup mode so all changed made by the users are written to the diff file.
0x800The database is still in backup mode, but changes are being merged from the diff file into the main pages.
0xC00The current database state is unknown and changes need to be read from disc.

Hdr_shutdown_mask: The shutdown mask uses two bits to indicate the current database shutdown status, as follows:

Flag valueDescription
0x00 (Both bits 7 and 12 are zero)Database is not shutdown. Any valid user can connect.
0x80The database has been shutdown to, or started up in multi-user maintenance mode. The database can only be conncted to by SYSDBA or the database owner.
0x1000The database has been fully shutdown. No connections are permitted.
0x1080The database has been shutdown to, or started up in single-user maintenance mode. Only one SYSDBA or database owner connection is permitted.

back to top of page

hdr_creation_date: Eight bytes, signed. Bytes 0x2c - 0x33 on the page. The data and time (in Firebird's own internal format) that the database was either originally created/rewritten or created from a backup.

hdr_attachment_id: Four bytes, signed. Bytes 0x34 - 0x37 on the page. The ID number that will be assigned to the next connection to this database. As this is signed, the maximum value here is 232-1 and any database which reaches this maximum value must be backed up and restored in order to allow new connections. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the databasehave this field set to zero.

hdr_shadow_count: Four bytes, signed. Bytes 0x38 - 0x3c on the page. Holds the event count for shadow file synchronisation for this database. The remaining files in the database have this field set to zero.

hdr_implementation: Two bytes, signed. Bytes 0x3c and 0x3d on the page. This is a number which indicates the environment on which the database was originally created. It is used to determine if the database file can be used sucessfully on the current hardware. This avoids problems caused by little-endian numerical values as compared with big-endian, for example.

hdr_ods_minor: Two bytes, unsigned. Bytes 0x3e and 0x3f on the page. The current ODS minor version.

hdr_ods_minor_original: Two bytes, unsigned. Bytes 0x40 and 0x41 on the page. The ODS minor version when the database was originally created.

hdr_end: Two bytes, unsigned. Bytes 0x42 and 0x43 on the page. The offset on the page where the hdr_data finishes. In other words, where a new clumplet will be stored if required. This is effectively a pointer to the current location of hdr_end (see clumplet details below) on this page.

hdr_page_buffers: Four bytes, unsigned. Bytes 0x44 - 0x47 on the page. Holds the number of buffers to be used for the database cache, or zero to indicate that the default value should be used. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

hdr_bumped_transaction: Four bytes, signed. Bytes 0x48 - 0x4b on the page. Used to be used for the bumped transaction ID for log optimisation, but is currently always set to 0x01. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

hdr_oldest_snapshot: Four bytes, signed. Bytes 0x4c - 0x4f on the page. Holds the transaction number for the oldest snapshot of active transactions. This is also documented as the confusing and redundant variant of Oldest Active Transaction.

hdr_backup_pages: Four bytes, signed. Bytes 0x50 - 0x53 on the page. Holds the number of pages in the database currently locked for a backup using nbackup. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_misc: Twelve bytes. Bytes 0x54 - 0x5f on the page. Set to zero. These 12 bytes are currently unused.

back to top of page

The following is an example of a header page from a multi-file database on a little-endian system:

 00000000 01 00 39 30 08 00 00 00   00 00 00 00 00 00 00 00   Standard header
 00000010 00 10                                               hdr_page_size
 00000012 0b 80                                               hdr_ods_version
 00000014 03 00 00 00                                         hdr_PAGES
 00000018 00 00 00 00                                         hdr_next_page
 0000001c 01 00 00 00                                         hdr_oldest_transaction
 00000020 02 00 00 00                                         hdr_oldest_active
 00000024 05 00 00 00                                         hdr_next_transaction
 00000028 00 00                                               hdr_sequence
 0000002a 00 01                                               hdr_flags
 0000002c 5e d7 00 00 f4 79 00 23                             hdr_creation_date
 00000034 01 00 00 00                                         hdr_attachment_id
 00000038 00 00 00 00                                         hdr_shadow_count
 0000003c 13 00                                               hdr_implementation
 0000003e 01 00                                               hdr_ods_minor
 00000040 01 00                                               hdr_ods_minor_original
 00000042 93 00                                               hdr_end
 00000044 00 00 00 00                                         hdr_page_buffers
 00000048 01 00 00 00                                         hdr_bumped_transaction
 0000004c 02 00 00 00                                         hdr_oldest_snapshot
 00000050 00 00 00 00                                         hdr_backup_pages
 00000054 00 00 00 00 00 00 00 00 00 00 00 00                 hdr_misc
 00000060                                                     hdr_data[]

Note:From Firebird 2.x onwards, there is a system table - MON$DATABASE which has a copy of all of the above data in an easy to obtain format:

 tux> isql employee
 Database: employee 

 SQL> show table mon$database;
 MON$DATABASE_NAME             (RDB$FILE_NAME) VARCHAR(253) Nullable
 MON$PAGE_SIZE                 (RDB$PAGE_SIZE) SMALLINT Nullable
 MON$ODS_MAJOR                 (RDB$ODS_NUMBER) SMALLINT Nullable
 MON$ODS_MINOR                 (RDB$ODS_NUMBER) SMALLINT Nullable
 MON$OLDEST_TRANSACTION        (RDB$TRANSACTION_ID) INTEGER Nullable
 MON$OLDEST_ACTIVE             (RDB$TRANSACTION_ID) INTEGER Nullable
 MON$OLDEST_SNAPSHOT           (RDB$TRANSACTION_ID) INTEGER Nullable
 MON$NEXT_TRANSACTION          (RDB$TRANSACTION_ID) INTEGER Nullable
 MON$PAGE_BUFFERS              (RDB$PAGE_BUFFERS) INTEGER Nullable
 MON$SQL_DIALECT               (RDB$SQL_DIALECT) SMALLINT Nullable
 MON$SHUTDOWN_MODE             (RDB$SHUTDOWN_MODE) SMALLINT Nullable
 MON$SWEEP_INTERVAL            (RDB$SWEEP_INTERVAL) INTEGER Nullable
 MON$READ_ONLY                 (RDB$SYSTEM_FLAG) SMALLINT Nullable
 MON$FORCED_WRITES             (RDB$SYSTEM_FLAG) SMALLINT Nullable
 MON$RESERVE_SPACE             (RDB$SYSTEM_FLAG) SMALLINT Nullable
 MON$CREATION_DATE             (RDB$TIMESTAMP) TIMESTAMP Nullable
 MON$PAGES                     (RDB$COUNTER) BIGINT Nullable
 MON$STAT_ID                   (RDB$STAT_ID) INTEGER Nullable
 MON$BACKUP_STATE              (RDB$BACKUP_STATE) SMALLINT Nullable

 SQL> commit;
 SQL> quit;

back to top of page

Hdr_data: The variable data area on the header page begins at offset 0x60. Data stored here is held in clumplets and there are a number of different clumplet types, see below. This area is used to store file names for the next file and other miscellaneous pieces of data relating to the database.

The format of each clumplet is as follows:

Type_byte: The first byte - unsigned - in each clumplet determines the type of data stored within the clumplet. There are a number of different clumplet types:

Type nameValueDescription
HDR_end0x00End of clumplets.
HDR_root_file_name0x01Original name of the root file for this database.
HDR_journal_server0x02Name of the journal server.
HDR_file0x03Secondary file name.
HDR_last_page0x04Last logical page of the current file.
HDR_unlicemsed0x05Count of unlicensed activity. No longer used.
HDR_sewwp_interval0x06Number of transactions between sweep.
HDR_log_name0x07Replay log name.
HDR_journal_file0x08Intermediate journal file name.
HDR_password_file_key0x09Key to compare with the password database.
HDR_backup_info0x0aWrite Ahead Log (WAL) backup information. No longer used.
HDR_cache_file0x0bShared cache file. No longer used.
HDR_difference_file0x0cDiff file used during the times when the database is in backup mode.
HDR_backup_guid0x0dUID generated when database is in backup mode. Overwritten on subsequent backups.

Length_byte: The second byte - again unsigned - in each clumplet specifies the size of the data that follows.

Data: The next n bytes are the actual clumplet data. The miscellaneous data stored in the header from the above database, at hdr_data, is shown below.

 00000060 03                                                Type = HDR_file
 00000061 2b                                                Length = 43 bytes
 00000062 2f 75 30 30 2f 66 69 72 65 62 69 72 64 2f         Data '/u00/firebird/'
 00000070 64 61 74 61 62 61 73 65 73 2f 6d 75 6c 74 69 5f        'databases/multi_'
 00000080 65 6d 70 6c 6f 79 65 65 2e 66 64 62 31                 'employee.fdb1'

 0000008d 04                                                Type = HDR_last_page
 0000008e 04                                                Length = 4 bytes
 0000008f a2 00 00 00                                       Data 0xa2 = 162

 00000093 00                                                Type = HDR_end.

From the above we can see that in our multi-file database:

  • The next file (after this one) is named '/u00/firebird/databases/multi_employee.fdb1'.
  • The current file has 162 pages only - and with a 4Kb page size this means that the current file should be 663,552 bytes in size, which a quick run of ls -l will confirm.
  • HDR_end is located at offset 0x93 in the page, exactly as the header field hdr_end told us. (See above).

See also:
Firebird Database Cache Buffer: The Firebird cache
Firebird for the database expert: episode 2 - Page types

back to top of page
<< Standard database page header | Firebird Internals | Page Inventory Page - type 0x02 >>