ディスク上のどのファイルがPostgreSQLテーブルに対応するかを判断する方法

ディスク上のどのファイルがテーブルに対応するかを判断する必要がある場合があります。 base / 16499/19401などの数字で満たされたパスがあり、それを把握したい場合。 ファイル名に言及しているエラーメッセージを見ることができます、例えば:

ERROR: could not read block 11857 of relation base/16396/3720450: read only 0 of 8192 bytes 

関係の方法を探す

次を使用して、テーブルへのパスを確認できます。

 SELECT pg_relation_filepath('tablename'); 

しかし、パスからオブジェクトの名前を取得する逆のプロセスはどうですか? pg_filenode_relationという関数がありますが、これはこれに適しているように思えますが、使用するには、このファイルが属する特定のデータベースに接続する必要があります。

ファイルパス構造

PostgreSQLの最新バージョンでテーブルとデータベースへのパスを決定する方法は次のとおりです。 (古いバージョンは別の形式を使用しており、これについてはこちらで読むことができます )。

パスには3つの主なオプションがあります。



一般的な関係については最後に説明します。 最も頻繁に出会う最も一般的な最初の2つのオプションについては、パスの最後の部分は同一で、OIDベースとOIDの関係です。

oid relationship 」ではなく、「 filenode id of relationship 」という表現を使用したことに注意してください。 これは、PostgreSQLがpg_relfilenode.mapと呼ばれるファイルに各データベース/テーブルスペースのrelfilenodeマップを持っているためです。 テーブルファイル名は必ずしもpg_classの OIDと一致するわけではなく、 VACUUM FULL、TRUNCATEなどの実行後に変更できます。 例:

 test=> select pg_relation_filepath('a'); pg_relation_filepath ---------------------- base/16385/101565 (1 row) test=> VACUUM FULL a; VACUUM test=> select pg_relation_filepath('a'); pg_relation_filepath ---------------------- base/16385/101577 (1 row) 

だから。 このパスを関係名に戻す方法は?

データベースOIDとファイルノードIDの関係

この記事の最初からエラーが発生したとします。 それはいくつかの部分に分けることができます:


次に、それぞれの意味を検討します。

OIDデータベース定義

まず、このPostgreSQlプロセスのデータベースに接続して実行する必要があります。

 select datname from pg_database where oid = 16396 

(またはあなたが持っている他のoidベース)。 これにより、データベース名が返されます。

その後、このデータベースに接続する必要があります。

relfilenodesをバージョン9.4に逆変換

バージョン9.4以降を使用している場合、次の部分は簡単です。

 SELECT pg_filenode_relation(0, 3720450); 

(0は「デフォルトのテーブルスペース」を意味します)

この関数は、relfilenodeの逆変換を実行します。 そうすれば、テーブルの名前が表示されるだけです。 受信したテーブル名が現在のsearch_pathに属している場合、何らかのスキームとの接続は表示されません。 SET search_path = '';を使用できます 関数を実行する前に、回路へのパスが示されるようにします。

正しいデータベースに接続する必要があります。そうしないと、間違った回答が受信されるか、回答がまったく受信されません。

バージョン9.3でのRelfilenodesの逆変換

バージョン9.3以前を使用している場合、テーブルが置かれているデータベースに接続し、 pg_classに対して次のクエリを実行する必要があります。

 select n.nspname AS tableschema, c.relname AS tablename from pg_class c inner join pg_namespace n on (c.relnamespace = n.oid) where c.relfilenode = 3720450; 

(またはテーブルのその他の受信したrelfilenode id)。

これにより、このエラーがどのテーブルに属しているかがわかります。

結果なし?

まあ、それは通常役立ちます。

Relfilenodeをnullにすることもできます。これは、ファイルがpg_relfilenode.mapを介して配置されることを意味します。 これは、一般的なシステムディレクトリ、それらのインデックス、TOASTテーブルなどの典型的なシナリオです。 たとえば、 pg_databasepg_class 、およびpg_procです。

サーキットはどうですか?

スキーマ(名前空間)がパスに表示されないことに気付きましたか?

PostgreSQLでは、スキーマはデータベース内の名前空間にすぎません。 テーブルが物理的にディスクのどこに保存されるかには影響しません。

他の表領域パス

私が遭遇した最近のケースは次のエラーでした:

 ERROR: could not truncate file "pg_tblspc / 16709 / PG_9.3_201306121 / 16499/19401" to 8 blocks: Permission denied 

パスはpg_tblspcで始まるため、これはデフォルトのテーブルスペースではありません。

テーブルを見つけるプロセスは実際には同じです。 pg_tblspc / nnn / PG_n.n_nnnnnn / partを無視して、上記のデフォルトの表スペースの場合で説明したように、すぐにdatabase_oid / relation_oidに集中できます。 これを行うには、パスの意味を理解します。

したがって、エラーテキストは次の部分に分割されます。


データベースoidとテーブルベースのrelfilenode idについてはすでに説明しました。 表スペースと違いはありません。他の場所でのみ開始されます。

では、表領域の部分はどうでしょうか?

pg_tblspcはPostgreSQLデータディレクトリ内のディレクトリで、テーブルスペース(またはNTFS、それらの接続ポイント)のすべての位置へのシンボリックリンクが含まれています 。 各シンボリックリンクの名前は、oidテーブルスペースに基づいています。 これは、PostgreSQLがテーブルスペースを見つける方法です。 表スペースに対するSQLコマンドは、これらのリンクで動作します。

OIDは、 以下からわかるように、表スペースのpg_tablespaceエントリーを指します。

 select spcname from pg_tablespace where oid = 16709; 

テーブルスペースディレクトリ内には、PostgreSQLのバージョンに対応する名前を持つ別のディレクトリがあります。 このバージョンでは静的であり、唯一のアプリケーションは、たとえばpg_upgrade中など、同じテーブルスペースへの複数のPostgreSQLプロセスの複数アクセスです。 通常、エントリは1つだけです。

一般に、構造はベース/パスと同じです-最初にOIDデータベース、次にOID関係。

グローバル(一般)テーブル

エラーの3番目のカテゴリがあります。それを観察した場合、間違いなく問題が発生しています。 PostgreSQLには共通のディレクトリがあります-各データベースで同じコンテンツを持つテーブル。 それらは、relfilenode id 16709の特別なテーブルスペースにあります。

それらへのパスはベースではなくグローバルで始まり、データベースoidを持つコンポーネントはありません。

共有ディレクトリはpg_classの relfilenodeでマークされていません。 つまり、たとえばpg_classの pg_databaseを見ることができません。 pg_filenode_relationは、デフォルトのテーブルスペースoidで呼び出すか、1664グローバルテーブルスペースoidで呼び出すかに関係なく、nullを返します。

これを明確にすることは、解析されたリンクを含む後続の記事のトピックです。

もちろん、共有ディレクトリで問題が発生している場合、原則としてデータベースを起動することはできません。

ダメージに対処する

データベースの破損は発生しません。 しかし、それはとにかく起こります。 ハードウェア、カーネルバグ、またはファイルシステムの問題、信頼できるディスクの潮流、バグのあるストレージネットワーク、そしてもちろんPostgreSQLのバグをコミットすることについて嘘をつくSSDです。 データベースの損傷が疑われる場合は、何かを行う前に、 Wikiページの破損に関するアドバイスを読んでそれに従ってください

内部

すべての動作を確認するには、src / include / common / relpath.hでrelpathbackendマクロを実行します。 src / common / relpath.cのGetRelationPathを呼び出します。

このマニュアルでは、ディスク上のデータベース構造を考慮しています。 リンク

Source: https://habr.com/ru/post/J275125/


All Articles