こんにちは。サイオステクノロジー 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 (ファイルシステム) 上のシンボリックリンクで管理されているようです。