Edited at

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

More than 1 year has passed since last update.

相当の業務ボリュームの増加で、DBサーバー(※0)の容量が危機的になってきた。

対策として、世界に残り40枚(業者談)という高速ディスクのカードを購入し、増設を実施。

その増設領域への実体移動手段として、pg_repack を使用し、当面の問題解消に成功。

とある運用事例として世の中の役に立てばと思い、投稿。


  • (※0)


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




はじめに


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


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 のインストール方法については別立ての記事に。(もしくは公式をご参照。。)

  • 成功裏に増設・移動が少しできたが、事前の検証・把握を十分に行ったための結果だと思っている。


    • 予行演習・小規模実行が功を奏した。やはり、準備が大切。