🗿

pg_repackでテーブルスペースを移動して容量の危機を脱した2018.5.23

2021/05/03に公開

published_at: 2018-05-28


相当の業務ボリュームの増加で、DBサーバー(※0)の容量が危機的になってきた。
対策として、世界に残り40枚(業者談)という高速ディスクのカードを購入し、増設を実施。
その増設領域への実体移動手段として、pg_repack を使用し、当面の問題解消に成功。
とある運用事例として世の中の役に立てばと思い、投稿。

  • (※0)
    • PostgreSQL系のRDBMSで、付属のGUIツールがある有償製品を使用している

はじめに

テーブルスペース について

  • テーブル空間を使用することで、PostgreSQLのディスクレイアウトを制御することができる。ボリュームの容量不足時に対策可能。

(PostgreSQL 9.4.5文書 21.6. テーブル空間)
https://www.postgresql.jp/document/9.4/html/manage-ag-tablespaces.html

pg_repack について

  • オンライン中に動作させることができる、テーブルやインデックスの再編成ツール。

https://github.com/reorg/pg_repack

調整前の状態

なかなかの逼迫状態

容量(df -h) サイズ 使用 残り 使用% マウント位置
/dev/fioa1 2.2T 1.7T 464G 79% /mnt/fio/(以下略)

ディスクの増設

シャットダウン前に

増設前にシャットダウンが必要なので準備として以下を実施

  1. サービスをメンテナンスモードにして外からのアクセスをなくす
  2. 内部で定期的に実行されるバックグラウンド処理を全て止める
  3. この時点でWALファイルが出なくなっている状態と想定していたがautovacuumが回っていてなかなか出るのが止まらなかったのでDBMSを停止
  4. これで完全にWALファイルの出力が止まったので、 バックアップサーバーに念のためWALファイルをコピーして(※1)、シャットダウン。
  • (※1)
    • 万一の、サーバーが上がってこないケースに備えて。

カード増設、ドライバ・ファームウェアのアップデート

(丸々業者にやってもらいました)
(とはいえ実施タイミングのキュー出しは発注側の指示なので主導的に計画・想定)
(過程で必要になるリモートアクセスコントローラへのログインはWindowsのPCを持参して対応)(※2)
(2回ほどOS再起動をはさみ、使用可能になる)

  • (※2)
    • 新しいバージョンのものだったのでこのケースでは大丈夫でしたが、古いiDRACなどの場合は仮想コンソールを起動するにはJavaのバージョンに注意が必要。

pg_repack で テーブルスペース移動

増設直後(フォーマット・マウントコマンドは割愛)

容量(df -h) サイズ 使用 残り 使用% マウント位置
/dev/fioa1 2.2T 1.7T 464G 79% /mnt/fio/(以下略)
/dev/fiob 3.0T 33M 3.0T 1% /mnt/fio2/(以下略)

PostgreSQL起動

設定を確認・調整のうえで起動。

テーブルスペースを作成

/mnt/fio2 配下にテーブルスペース用のディレクトリを作成し、
オーナー・パーミッションを postgres:postgres 700 にしたうえで、
GUIでテーブルスペース space2 を作成。(※3)
なお、レプリケーション先にも同一のディレクトリパスを整備しておかないと、テーブルスペース作成時にレプリケーションが切れる。

  • (※3)
    • 有償製品ならではのGUIを利用。ちなみに以下のようなSQLに相当(おそらく)
      • CREATE TABLESPACE space2 LOCATION '/mnt/fio2/(以下略)';

デフォルトテーブルスペースの変更

今後の書き込み先が space2 となるように以下のクエリを実行

ALTER DATABASE large-db SET default_tablespace TO 'space2';

現在のデフォルトテーブルスペースを確認する方法は、各DBで以下コマンドの実行

SHOW default_tablespace;

もしくはテーブル単位でテーブルスペースを確認できるので新規テーブルに対して以下SQL

SELECT
  u.relname AS table_name,
  current_database() AS database_name,
  t.tablespace AS tablespace_name
FROM
  pg_stat_user_tables u
  JOIN pg_tables t ON u.relname = t.tablename
WHERE
  relname = '(新規テーブル名)';

テーブルスペース移動スクリプト

第1引数にテーブルリスト、第2引数にDB名、第3引数に移動先のテーブルスペースを指定するスクリプトが以下のようになります。

  • num は進捗を把握する意図の変数、pg_repack 前後の pg_size_pretty 関数は再編成効果を表示する意図のコマンドになります
  • pg_repack の前の time コマンドは、コンソールに表示されますが流れが速すぎて1つ1つを確認できないかもしれません
exec_repack_mv_space.sh
# !/bin/bash
tbl=$(cat $1)
db=$2
toSpace=$3

num=0
for t in ${tbl[@]}
do
        num=$((num + 1))
        echo "----- [$num] ----- ${t}";
        psql -U postgres -h localhost -t -c"SELECT pg_size_pretty(pg_total_relation_size('${t}')) AS tbl_size" ${db}
        time pg_repack -U postgres -h localhost -d ${db} -t ${t} -s ${toSpace} -S
        psql -U postgres -h localhost -t -c"SELECT pg_size_pretty(pg_total_relation_size('${t}')) AS tbl_size" ${db}
        echo "";
done

これを、chmod +x exec_repack_mv_space.sh したうえで 以下のように実行します
./exec_repack_mv_space.sh tbl-list large-db space2

調整後の状態

テーブルスペース移動はメンテナンスの時間のうちで、と思っていましたが時間内にリストが終わり切らず。。
しかしリストが終わるまでスクリプト実行を継続しましたがサービス影響は報告されずに済みました。
影響なく済んだと捉えています。 :sweat_smile:

容量(df -h) サイズ 使用 残り 使用% マウント位置
/dev/fioa1 2.2T 1.4T 770G 65% /mnt/fio/(以下略)
/dev/fiob 3.0T 208G 2.8T 7% /mnt/fio2/(以下略)

おわりに

  • 今後も空き容量を見て pg_repack の運用が必要になりそうだが、当面は凌いだと言えそう。
    • かなり強力でありがたい運用ツールとして利用していきそう。
  • 容量が膨らみそうなDBでも、最初からテーブルスペースを利用することで長期的な稼働が見込めそう。
    • 運用にまあまあ神経使いそうですが。
  • 感じた pg_repack の傾向など(個人の見解です)
    • 実行時はCPU負荷がそれなりにかかる感じ。サービス影響に適度に気をつけたほうがよさそう。
    • 大きいテーブルの pg_repack はかなり時間がかかるようだ。。
    • 処理にはコア1つしか使わないようだ。
      • リソースが潤沢であればいくらか並列実行してよさそう。PostgreSQLの傾向?

その他

  • 現在のテーブルスペースを把握する方法があまりないようで、メタコマンド ¥l+ で表示されるDB毎の Tablespace は当初のもののようだ。
  • テーブルスペースの移動をしない pg_repack を実行する場合、exec_repack_mv_space.sh から -s ${toSpace} -S を外せばよいかと。
  • pg_repack のインストール方法については別立ての記事に。(もしくは公式をご参照。。)
  • 成功裏に増設・移動が少しできたが、事前の検証・把握を十分に行ったための結果だと思っている。
    • 予行演習・小規模実行が功を奏した。やはり、準備が大切。

Discussion