PostgreSQL のテーブルスペースのパスの情報について調べてみた

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

今回は業務にて機会があったため PostgreSQL のテーブルスペースについて少し調べてみました。(※以下の内容は PostgreSQL 10.1 にて検証/調査しています。)

(https://www.postgresql.org/docs/10/static/manage-ag-tablespaces.html)

■はじめに

PostgreSQL では “テーブルスペース” という機能を使って特定のテーブルのファイル等をデフォルトとは異なるディレクトリに格納することが可能です。

この “OS 上のディレクトリ (パス)” の情報をどのように管理 (保持) しているのか?を調査してみました。

■検証

実際にテーブルスペースを作成してみると、pg_tablespace というシステムカタログにテーブルスペースの情報が格納されますが、この pg_tablespace に OS 上のディレクトリの情報は含まれていませんでした。

このシステムカタログ pg_tablespace にて OS 上のパスの情報を保持しているのかと想像していましたが、どうやら違うようです。

postgres=# CREATE TABLESPACE hoge LOCATION '/tmp/test_dir';
CREATE TABLESPACE
postgres=# 
postgres=# SELECT oid, * FROM pg_tablespace;
  oid  |  spcname   | spcowner | spcacl | spcoptions 
-------+------------+----------+--------+------------
  1663 | pg_default |       10 |        | 
  1664 | pg_global  |       10 |        | 
 16438 | hoge       |       10 |        | 
(3 rows)

テーブルスペースの OS 上のディレクトリの情報は以下の様に psql のメタコマンド “\db” の “Location” にて確認することができます。この “\db” がどこから情報を取得しているのかを探ってみました。

postgres=# \db
          List of tablespaces
    Name    |  Owner   |   Location    
------------+----------+---------------
 hoge       | postgres | /tmp/test_dir
 pg_default | postgres | 
 pg_global  | postgres | 
(3 rows)

log_statement を利用して “\db” が内部で実行している SQL をログから確認したところ pg_tablespace_location() という関数で “Location” の値を取得しているようです。

SELECT spcname AS "Name",
        pg_catalog.pg_get_userbyid(spcowner) AS "Owner",
        pg_catalog.pg_tablespace_location(oid) AS "Location"
        FROM pg_catalog.pg_tablespace
        ORDER BY 1;

実際に、先ほど作成したテーブルスペース “hoge” の OID (16438) を引数にして pg_tablespace_location() を実行すると、OS 上のパスが出力されました。ということで、この pg_tablespace_location() がどこから情報を取得しているのかを探る必要がありそうです。

postgres=# SELECT pg_tablespace_location(16438);
 pg_tablespace_location 
------------------------
 /tmp/test_dir
(1 row)

この pg_tablespace_location() のソースコードを覗いてみると、以下のようなコードになっていました。

コード内のコメントにも記載されていますが、”pg_tblspc/” というシンボリックリンクから情報を取得しているようです。

[src/backend/utils/adt/misc.c (抜粋)]
 459 /*
 460  * pg_tablespace_location - get location for a tablespace
 461  */
 462 Datum
 463 pg_tablespace_location(PG_FUNCTION_ARGS)
 464 {

(omission)

 487         /*
 488          * Find the location of the tablespace by reading the symbolic link that
 489          * is in pg_tblspc/.
 490          */
 491         snprintf(sourcepath, sizeof(sourcepath), "pg_tblspc/%u", tablespaceOid);
 492 
 493         rllen = readlink(sourcepath, targetpath, sizeof(targetpath));

(omission)

 506         PG_RETURN_TEXT_P(cstring_to_text(targetpath));

(omission)

 513 }

実際に OS 側からこのディレクトリ ($PGDATA/pg_tblspc) を確認してみると、作成したテーブルスペース “hoge” の OID “16438” という名前でシンボリックリンクが作成されており、そのリンク先がテーブルスペース作成時に指定したパス “/tmp/test_dir” になっていました。

[postgres@localhost data]$ ls -l ./pg_tblspc/
合計 0
lrwxrwxrwx 1 postgres postgres 13  1月 25 12:07 16438 -> /tmp/test_dir

■最後に

ということで、「”OS 上のディレクトリ (パス)” の情報をどの様に管理 (保持) しているのか?」という問いに対しては、「$PGDATA/pg_tblspc 配下のシンボリックリンクで管理している」というのが答えになりそうです。

PostgreSQL は pg_class 等のシステムカタログにて内部の情報を保持していることが多いので、テーブルスペースにおける “OS 上のパス” の情報もシステムカタログに格納されているのかと思っていましたが、パスの情報は直接システムカタログに登録されている訳ではなく、OS (ファイルシステム) 上のシンボリックリンクで管理されているようです。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です