Le module pageinspect
fournit des fonctions qui vous
permettent d'inspecter le contenu des pages de la base de données à un bas
niveau, ce qui utile pour le débogage. Toutes ces fonctions ne sont
utilisables que par les super-utilisateurs.
get_raw_page(relname text, fork text, blkno int) returns bytea
get_raw_page
lit le bloc spécifié de la relation
nommée et renvoie une copie en tant que valeur de type
bytea
. Ceci permet la récupération de la copie cohérente à
un instant t d'un bloc spécifique. fork
devrait être 'main'
pour les données, et
'fsm'
pour la carte des espaces libres,
'vm'
pour la carte de visibilité ou
'init'
.
get_raw_page(relname text, blkno int) returns bytea
Une version raccourcie de get_raw_page
, pour ne
lire que la partie des données. Équivalent à
get_raw_page(relname, 'main', blkno)
.
page_header(page bytea) returns record
page_header
affiche les champs communs à toutes les
pages des tables et index PostgreSQL.
L'image d'une page obtenu avec get_raw_page
doit
être passé en argument. Par exemple :
test=# SELECT * FROM page_header(get_raw_page('pg_class', 0)); lsn | checksum | flags | lower | upper | special | pagesize | version | prune_xid -----------+----------+--------+-------+-------+---------+----------+---------+----------- 0/24A1B50 | 0 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0
Les colonnes renvoyées correspondent aux champs de la structure
PageHeaderData
. Voir
src/include/storage/bufpage.h
pour les détails.
Le champ checksum
est la somme de contrôle
stockée dans la page, qui peut être incorrecte si la page est d'une
manière ou d'une autre corrompue. Si les sommes de contrôle des données
ne sont pas activées pour cette instance, alors la valeur stockée n'a
aucune signification.
page_checksum(page bytea, blkno int4) returns smallint
page_checksum
calcule la somme de contrôle pour la
page, comme si elle était citée au numéro de bloc passé en paramètre.
Une image de page obtenue avec get_raw_page
devrait
être passée en argument. Par exemple :
test=# SELECT page_checksum(get_raw_page('pg_class', 0), 0); page_checksum --------------- 13443
Veuillez noter que la somme de contrôle dépend du numéro de bloc, ainsi des numéros de blocs qui se correspondent devraient être passé (sauf lors de débugage ésotériques).
Les sommes de contrôle calculées avec cette fonction peuvent être
comparées avec le champ checksum
retournée
par la fonction page_header
. Si les sommes de
contrôle des données sont activées sur cette instance, alors les deux
valeurs devraient être égales.
fsm_page_contents(page bytea) returns text
fsm_page_contents
montre la structure interne du
nœud d'une page FSM. Par exemple :
test=# SELECT fsm_page_contents(get_raw_page('pg_class', 'fsm', 0));
La sortie est une chaîne de texte multiligne, avec une ligne par nœud dans l'arbre binaire au sein de la page. Seuls ces nœuds qui ne valent pas zéro sont affichés. Le pointeur appelé « next », qui pointe vers le prochain slot à être retourné depuis la page, est également affiché.
Voir src/backend/storage/freespace/README
pour plus
d'information sur la structure d'une page FSM.
heap_page_items(page bytea) returns setof record
heap_page_items
affiche tous les pointeurs de ligne
dans une page de table. Pour les pointeurs de ligne en utilisation, les
en-têtes de ligne ainsi que les données des lignes sont aussi affichées.
Toutes les lignes sont affichées, qu'elles soient ou non visibles dans
l'image MVCC au moment où la page brute a été copiée.
Une image d'une page de table obtenue avec
get_raw_page
doit être fournie en argument. Par
exemple :
test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0));
Voir src/include/storage/itemid.h
et
src/include/access/htup_details.h
pour des
explications sur les champs renvoyés.
La fonction heap_tuple_infomask_flags
peut être
utilisée pour déchiffrer les drapeaux de
t_infomask
et
t_infomask2
pour les lignes de la table.
tuple_data_split(rel_oid oid, t_data bytea, t_infomask integer, t_infomask2 integer, t_bits text [, do_detoast bool]) returns bytea[]
tuple_data_split
divise les données d'une ligne en
attributs de la même façon que le fait le moteur.
test=# SELECT tuple_data_split('pg_class'::regclass, t_data, t_infomask, t_infomask2, t_bits) FROM heap_page_items(get_raw_page('pg_class', 0));
Cette fonction doit être appelée avec les mêmes arguments que ce qui est
renvoyé par heap_page_items
.
Si do_detoast
est true
, la
donnée TOAST sera traitée. La valeur par défaut est
false
.
heap_page_item_attrs(page bytea, rel_oid regclass [, do_detoast bool]) returns setof record
heap_page_item_attrs
est équivalent à
heap_page_items
sauf qu'elle renvoie les données
brutes de la ligne sous la forme d'un tableau d'attributs pouvant en
option être traités par do_detoast
(comportement
désactivé par défaut).
Une image de la page HEAP obtenue avec get_raw_page
doit être fournie comme argument. Par exemple :
test=# SELECT * FROM heap_page_item_attrs(get_raw_page('pg_class', 0), 'pg_class'::regclass);
heap_tuple_infomask_flags(t_infomask integer, t_infomask2 integer) returns record
heap_tuple_infomask_flags
décode les champs
t_infomask
et
t_infomask2
renvoyés par
heap_page_items
en un ensemble de tableaux composés
de noms de drapeau, lisibles par un humain, avec une colonne pour tous
les drapeaux et une colonne pour les drapeaux composés. Par
exemple :
test=# SELECT t_ctid, raw_flags, combined_flags FROM heap_page_items(get_raw_page('pg_class', 0)), LATERAL heap_tuple_infomask_flags(t_infomask, t_infomask2) WHERE t_infomask IS NOT NULL OR t_infomask2 IS NOT NULL;
Cette fonction doit être appelée avec les mêmes arguments que les
attributes de retour de heap_page_items
.
Les drapeaux combinés sont affichés pour les macros de niveau source
prenant en compte la valeur de plus d'un bit, comme par exemple
HEAP_XMIN_FROZEN
.
Voir src/include/access/htup_details.h
pour des
explications sur les noms des drapeaux renvoyés.
bt_metap(relname text) returns record
bt_metap
renvoie des informations sur une méta-page
d'un index B-tree. Par exemple :
test=# SELECT * FROM bt_metap('pg_cast_oid_index'); -[ RECORD 1 ]-----------+------- magic | 340322 version | 4 root | 1 level | 0 fastroot | 1 fastlevel | 0 oldest_xact | 582 last_cleanup_num_tuples | 1000 allequalimage | f
bt_page_stats(relname text, blkno int) returns record
bt_page_stats
renvoie un résumé des informations
sur les pages enfants des index B-tree. Par exemple :
test=# SELECT * FROM bt_page_stats('pg_cast_oid_index', 1); -[ RECORD 1 ]-+----- blkno | 1 type | l live_items | 224 dead_items | 0 avg_item_size | 16 page_size | 8192 free_size | 3668 btpo_prev | 0 btpo_next | 0 btpo | 0 btpo_flags | 3
bt_page_items(relname text, blkno int) returns setof record
bt_page_items
renvoie des informations détaillées
sur tous les éléments d'une page d'index btree. Par exemple :
test=# SELECT itemoffset, ctid, itemlen, nulls, vars, data, dead, htid, tids[0:2] AS some_tids FROM bt_page_items('tenk2_hundred', 5); itemoffset | ctid | itemlen | nulls | vars | data | dead | htid | some_tids ------------+-----------+---------+-------+------+-------------------------+------+--------+--------------------- 1 | (16,1) | 16 | f | f | 30 00 00 00 00 00 00 00 | | | 2 | (16,8292) | 616 | f | f | 24 00 00 00 00 00 00 00 | f | (1,6) | {"(1,6)","(10,22)"} 3 | (16,8292) | 616 | f | f | 25 00 00 00 00 00 00 00 | f | (1,18) | {"(1,18)","(4,22)"} 4 | (16,8292) | 616 | f | f | 26 00 00 00 00 00 00 00 | f | (4,18) | {"(4,18)","(6,17)"} 5 | (16,8292) | 616 | f | f | 27 00 00 00 00 00 00 00 | f | (1,2) | {"(1,2)","(1,19)"} 6 | (16,8292) | 616 | f | f | 28 00 00 00 00 00 00 00 | f | (2,24) | {"(2,24)","(4,11)"} 7 | (16,8292) | 616 | f | f | 29 00 00 00 00 00 00 00 | f | (2,17) | {"(2,17)","(11,2)"} 8 | (16,8292) | 616 | f | f | 2a 00 00 00 00 00 00 00 | f | (0,25) | {"(0,25)","(3,20)"} 9 | (16,8292) | 616 | f | f | 2b 00 00 00 00 00 00 00 | f | (0,10) | {"(0,10)","(0,14)"} 10 | (16,8292) | 616 | f | f | 2c 00 00 00 00 00 00 00 | f | (1,3) | {"(1,3)","(3,9)"} 11 | (16,8292) | 616 | f | f | 2d 00 00 00 00 00 00 00 | f | (6,28) | {"(6,28)","(11,1)"} 12 | (16,8292) | 616 | f | f | 2e 00 00 00 00 00 00 00 | f | (0,27) | {"(0,27)","(1,13)"} 13 | (16,8292) | 616 | f | f | 2f 00 00 00 00 00 00 00 | f | (4,17) | {"(4,17)","(4,21)"} (13 rows)
Ceci est une page feuille B-tree. Tous les enregistrements qui pointent
vers la table sont des éléments de la liste d'éléments (qui, chacune,
stocke un total de 100 TID de 6 octets). Il existe aussi un
enregistrement « clé haute » sur
l'itemoffset
numéro 1.
ctid
est utilisé pour enregistrer des
informations codées sur chaque enregistrement dans cet exemple, bien que
les enregistrements des pages feuilles enregistrent souvent directement
le TID de la table dans le champ ctid
.
tids
est la liste de TID enregistrée sous la
forme d'une liste d'éléments.
Dans un bloc interne (non affiché), la partie du numéro de bloc dans le
champ ctid
esy un lien inférieur
(« downlink »), qui est un numéro de bloc vers un autre bloc
de l'index lui-même. La partie décalage
(offset, le deuxième nombre) du champ
ctid
enregistre des informations codées sur
l'enregistrement, telle que le nombre de colonnes présentes (le
troncage du suffixe pourrait avoir supprimé des colonnes de suffixe
inutiles). Les colonnes tronquées sont traitées comme ayant la valeur
« moins infini ».
htid
affiche un TID de table pour l'enregistrement,
quelque soit la représentation sous-jacente de l'enregistrement. Cette valeur
peut correspondre à un ctid
ou peut être décodée
parmi les représentations alternatives utilisées par les enregistrements
des listes d'éléments et par les enregistrements des pages internes. Les
enregistrements dans les pages internes ont habituellement la colonne TID
de la table tronquée, ce qui est représenté comme une valeur
htid
NULL.
Notez que le premier élément une page (autre que la dernière, toute page
avec une valeur différente de zéro dans le champ
btpo_next
) est la « clé haute » du
bloc, ce qui signifie que ces données (data
)
serve comme limite haute de tous les éléments apparaissant sur la page,
alors que son champ ctid
ne pointe pas vers
un autre bloc. De plus, sur les pages internes, le premier véritable
élément de donnée (le premier élément qui n'est pas une clé haute) a
chaque colonne tronquée, laissant aucune valeur réelle dans son champ
data
. Néanmoins, un tel élément n'a pas de
lien inférieur valide dans son champ ctid
.
Pour plus de détails sur la structure des index B-tree, voir Section 63.4.1. Pour plus de détails sur la déduplication et les listes d'éléments, voir Section 63.4.2.
bt_page_items(page bytea) returns setof record
Il est également possible de passer une page à
bt_page_items
comme une valeur de type
bytea
. Une image de page obtenue avec
get_raw_page
devrait être passé en argument. Ainsi
le précédent exemple pourrait également être réécrit ainsi :
test=# SELECT itemoffset, ctid, itemlen, nulls, vars, data, dead, htid, tids[0:2] AS some_tids FROM bt_page_items(get_raw_page('tenk2_hundred', 5)); itemoffset | ctid | itemlen | nulls | vars | data | dead | htid | some_tids ------------+-----------+---------+-------+------+-------------------------+------+--------+--------------------- 1 | (16,1) | 16 | f | f | 30 00 00 00 00 00 00 00 | | | 2 | (16,8292) | 616 | f | f | 24 00 00 00 00 00 00 00 | f | (1,6) | {"(1,6)","(10,22)"} 3 | (16,8292) | 616 | f | f | 25 00 00 00 00 00 00 00 | f | (1,18) | {"(1,18)","(4,22)"} 4 | (16,8292) | 616 | f | f | 26 00 00 00 00 00 00 00 | f | (4,18) | {"(4,18)","(6,17)"} 5 | (16,8292) | 616 | f | f | 27 00 00 00 00 00 00 00 | f | (1,2) | {"(1,2)","(1,19)"} 6 | (16,8292) | 616 | f | f | 28 00 00 00 00 00 00 00 | f | (2,24) | {"(2,24)","(4,11)"} 7 | (16,8292) | 616 | f | f | 29 00 00 00 00 00 00 00 | f | (2,17) | {"(2,17)","(11,2)"} 8 | (16,8292) | 616 | f | f | 2a 00 00 00 00 00 00 00 | f | (0,25) | {"(0,25)","(3,20)"} 9 | (16,8292) | 616 | f | f | 2b 00 00 00 00 00 00 00 | f | (0,10) | {"(0,10)","(0,14)"} 10 | (16,8292) | 616 | f | f | 2c 00 00 00 00 00 00 00 | f | (1,3) | {"(1,3)","(3,9)"} 11 | (16,8292) | 616 | f | f | 2d 00 00 00 00 00 00 00 | f | (6,28) | {"(6,28)","(11,1)"} 12 | (16,8292) | 616 | f | f | 2e 00 00 00 00 00 00 00 | f | (0,27) | {"(0,27)","(1,13)"} 13 | (16,8292) | 616 | f | f | 2f 00 00 00 00 00 00 00 | f | (4,17) | {"(4,17)","(4,21)"} (13 rows)
Tous les autres détails sont les même qu'expliqué au point précédent.
brin_page_type(page bytea) returns text
brin_page_type
renvoie le type de bloc du bloc
indiqué pour l'index BRIN donné ou renvoie une erreur
si le bloc n'est pas un bloc valide d'un index BRIN.
Par exemple :
test=# SELECT brin_page_type(get_raw_page('brinidx', 0)); brin_page_type ---------------- meta
brin_metapage_info(page bytea) returns record
brin_metapage_info
renvoie une information assortie
sur la métapage d'un index BRIN. Par exemple :
test=# SELECT * FROM brin_metapage_info(get_raw_page('brinidx', 0)); magic | version | pagesperrange | lastrevmappage ------------+---------+---------------+---------------- 0xA8109CFA | 1 | 4 | 2
brin_revmap_data(page bytea) returns setof tid
brin_revmap_data
renvoie la liste des identifiants
de lignes dans un bloc de type « range map » d'un index
BRIN. Par exemple :
test=# SELECT * FROM brin_revmap_data(get_raw_page('brinidx', 2)) LIMIT 5; pages --------- (6,137) (6,138) (6,139) (6,140) (6,141)
brin_page_items(page bytea, index oid) returns setof record
brin_page_items
renvoie les données enregistrées
dans le bloc de données de l'index BRIN. Par
exemple :
test=# SELECT * FROM brin_page_items(get_raw_page('brinidx', 5), 'brinidx') ORDER BY blknum, attnum LIMIT 6; itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | value ------------+--------+--------+----------+----------+-------------+-------------- 137 | 0 | 1 | t | f | f | 137 | 0 | 2 | f | f | f | {1 .. 88} 138 | 4 | 1 | t | f | f | 138 | 4 | 2 | f | f | f | {89 .. 176} 139 | 8 | 1 | t | f | f | 139 | 8 | 2 | f | f | f | {177 .. 264}
Les colonnes renvoyées correspondent aux champs des structures
BrinMemTuple
et
BrinValues
. Voir
src/include/access/brin_tuple.h
pour plus de
détails.
gin_metapage_info(page bytea) returns record
gin_metapage_info
renvoie des informations sur la
métapage d'un index GIN index metapage. Par
exemple :
test=# SELECT * FROM gin_metapage_info(get_raw_page('gin_index', 0)); -[ RECORD 1 ]----+----------- pending_head | 4294967295 pending_tail | 4294967295 tail_free_size | 0 n_pending_pages | 0 n_pending_tuples | 0 n_total_pages | 7 n_entry_pages | 6 n_data_pages | 0 n_entries | 693 version | 2
gin_page_opaque_info(page bytea) returns record
gin_page_opaque_info
renvoie des informations sur
la partie opaque d'un index GIN, comme le type de
bloc. Par exemple :
test=# SELECT * FROM gin_page_opaque_info(get_raw_page('gin_index', 2)); rightlink | maxoff | flags -----------+--------+------------------------ 5 | 0 | {data,leaf,compressed} (1 row)
gin_leafpage_items(page bytea) returns setof record
gin_leafpage_items
renvoie des informations sur les
données enregistrées dans un bloc feuille d'un index
GIN. Par exemple :
test=# SELECT first_tid, nbytes, tids[0:5] AS some_tids FROM gin_leafpage_items(get_raw_page('gin_test_idx', 2)); first_tid | nbytes | some_tids -----------+--------+---------------------------------------------------------- (8,41) | 244 | {"(8,41)","(8,43)","(8,44)","(8,45)","(8,46)"} (10,45) | 248 | {"(10,45)","(10,46)","(10,47)","(10,48)","(10,49)"} (12,52) | 248 | {"(12,52)","(12,53)","(12,54)","(12,55)","(12,56)"} (14,59) | 320 | {"(14,59)","(14,60)","(14,61)","(14,62)","(14,63)"} (167,16) | 376 | {"(167,16)","(167,17)","(167,18)","(167,19)","(167,20)"} (170,30) | 376 | {"(170,30)","(170,31)","(170,32)","(170,33)","(170,34)"} (173,44) | 197 | {"(173,44)","(173,45)","(173,46)","(173,47)","(173,48)"} (7 rows)
hash_page_type(page bytea) returns text
hash_page_type
renvoie le type de page de la page
d'index HASH donné. Par exemple :
test=# SELECT hash_page_type(get_raw_page('con_hash_index', 0)); hash_page_type ---------------- metapage
hash_page_stats(page bytea) returns setof record
hash_page_stats
retourne des informations sur un
bucket ou une page overflow d'un index HASH. Par
exemple :
test=# SELECT * FROM hash_page_stats(get_raw_page('con_hash_index', 1)); -[ RECORD 1 ]---+----------- live_items | 407 dead_items | 0 page_size | 8192 free_size | 8 hasho_prevblkno | 4096 hasho_nextblkno | 8474 hasho_bucket | 0 hasho_flag | 66 hasho_page_id | 65408
hash_page_items(page bytea) returns setof record
hash_page_items
retourne des informations sur les
données stockées dans un bucket ou une page overflow d'une page d'index
HASH. Par exemple :
test=# SELECT * FROM hash_page_items(get_raw_page('con_hash_index', 1)) LIMIT 5; itemoffset | ctid | data ------------+-----------+------------ 1 | (899,77) | 1053474816 2 | (897,29) | 1053474816 3 | (894,207) | 1053474816 4 | (892,159) | 1053474816 5 | (890,111) | 1053474816
hash_bitmap_info(index oid, blkno int) returns record
hash_bitmap_info
montre le statut d'un bit dans la
page de bitmap pour une page overflow en particulier d'un index
HASH. Par exemple :
test=# SELECT * FROM hash_bitmap_info('con_hash_index', 2052); bitmapblkno | bitmapbit | bitstatus -------------+-----------+----------- 65 | 3 | t
hash_metapage_info(page bytea) returns record
hash_metapage_info
retourne l'information stockée
dans la méta-page d'un index HASH index. Par
exemple :
test=# SELECT magic, version, ntuples, ffactor, bsize, bmsize, bmshift, test-# maxbucket, highmask, lowmask, ovflpoint, firstfree, nmaps, procid, test-# regexp_replace(spares::text, '(,0)*}', '}') as spares, test-# regexp_replace(mapp::text, '(,0)*}', '}') as mapp test-# FROM hash_metapage_info(get_raw_page('con_hash_index', 0)); -[ RECORD 1 ]------------------------------------------------------------------------------- magic | 105121344 version | 4 ntuples | 500500 ffactor | 40 bsize | 8152 bmsize | 4096 bmshift | 15 maxbucket | 12512 highmask | 16383 lowmask | 8191 ovflpoint | 28 firstfree | 1204 nmaps | 1 procid | 450 spares | {0,0,0,0,0,0,1,1,1,1,1,1,1,1,3,4,4,4,45,55,58,59,508,567,628,704,1193,1202,1204} mapp | {65}