PGroongaについてお勉強中の阿部です。
先日、PGroongaに便利関数を追加したのでその方法について説明します。 今回はSQLのみで実現しました。
PGroongaはPostgreSQLの拡張機能です。 PostgreSQLの拡張機能を1から開発する方法には触れませんが、PostgreSQLに関数を追加する方法を知りたい方の参考にはなると思います。
やること
やることは以下の3つです。
- 追加したい機能について考える
CREATE FUNCTION
に落とし込む- 所定のファイルに
CREATE FUNCTION
文などを追加する
1. 追加したい機能について考える
今回はレプリーケーションを利用しているときにPGroongaのWALで未適用のWALがないかを確認するための関数を追加します。
基本的にPGroongaのWALは自動で適用されないため、適用処理が実行されないとプライマリーとの差が開きます。それを検知するために使います。
参考: pgroonga_standby_maintainerモジュール
具体的な検知方法ですが以下の2つのときに未適用のWALがあると見なすことにしました。
- pgroonga_wal_status関数 の
current_*
とlast_*
が異なる場合current_*
は適用済みのPGroongaのWALの情報last_*
は適用されているかどうかに関わらず、現在存在しているPGroongaのWALの情報current_*
とlast_*
が異なるということは未適用のPGroongaのWALがある
- pg_stat_wal_receiver の
flushed_lsn
とlatest_end_lsn
が異なる場合flushed_lsn
: スタンバイ側で受信したWALの位置latest_end_lsn
: プライマリー側のWALの位置flushed_lsn
とlatest_end_lsn
が異なるということはプライマリーとスタンバイでWALの内容が違うので未適用のPGroongaのWALがある可能性がある
1の場合は pgroonga_wal_status
の結果でPGroongaのインデックスごとに未適用のWALの有無をチェックできるので、該当するPGroongaのインデックスのみを表示します。
2の場合はプライマリーとスタンバイでWALの状態が違うことまではわかりますが、未適用のPGroongaのWALの有無までは断定できません。 未適用のPGroongaのWALがある可能性もあるので、すべてのPGroongaのインデックスを表示することにしました。
2. CREATE FUNCTION
に落とし込む
まずは情報を取得するSQLを考える
「1. 追加したい機能について考える」で考えた情報を取得するSQLを考えます。
- pgroonga_wal_status関数 の
current_*
とlast_*
が異なる場合- 該当するPGroongaのインデックスのみを取得
- pg_stat_wal_receiver の
flushed_lsn
とlatest_end_lsn
が異なる場合- すべてのPGroongaのインデックスを表示
これらをSQLにすると以下の通りです。
SELECT name FROM pgroonga_wal_status()
WHERE current_block != last_block
OR current_offset != current_offset
OR current_size != last_size
OR EXISTS(
SELECT 1 FROM pg_stat_wal_receiver
WHERE flushed_lsn != latest_end_lsn
);
次に関数にする
考えた情報を取得するSQLを CREATE FUNCTION
で関数にします。
最終的なSQLをベースに解説します。
参考: CREATE FUNCTION
CREATE FUNCTION pgroonga_list_lagged_indexes()
RETURNS SETOF text AS '
SELECT name FROM pgroonga_wal_status()
WHERE current_block != last_block
OR current_offset != current_offset
OR current_size != last_size
OR EXISTS(
SELECT 1 FROM pg_stat_wal_receiver
WHERE flushed_lsn != latest_end_lsn
);
' LANGUAGE SQL
STRICT
PARALLEL SAFE;
pgroonga_list_lagged_indexes
が関数の名前です。今回は引数がないため ()
です。
引数を取る場合は ()
に必要な引数を記載します。
何か値を返す関数の場合は RETURNS
句で指定します。
この関数では未適用のWALがあるPGroongaのインデックス名を返すので RETURNS SETOF text
としました。
SETOF
を指定することで集合を返すことができます。
'
~ '
で囲まれているところが関数の本体です。('
で囲みましたが好きな文字を使うことができます。)
また LANGUAGE SQL
で関数の本体を記述している言語を指定します。この例ではSQL
です。
STRICT
を指定すると関数の引数に1つでもNULLがある場合、常にNULLを返すようになります。
この関数では関係ありませんが他のPGroongaの関数で指定されているので合わせました。
PARALLEL SAFE
を指定すると並列モードでも実行できます。
この CREATE FUNCTION
を実行すると'
~ '
で囲まれている関数の本体を実行し、その結果を返す関数が作れます。
3. 所定のファイルに CREATE FUNCTION
文などを追加する
3つのファイルに追加します。PGroongaでいうと以下の3つのファイルです。
data/pgroonga.sql
- インストール時に実行するSQL
data/pgroonga--<現バージョン>--<新バージョン>.sql
- バージョンアップ時に実行するSQL
- 例:
data/pgroonga--3.2.0--3.2.1.sql
- PGroongaを3.2.0から3.2.1へアップグレードするときに実行されます
data/pgroonga--<新バージョン>--<現バージョン>.sql
- ダウングレード時に実行するSQL
- 例:
data/pgroonga--3.2.1--3.2.0.sql
- PGroongaを3.2.1から3.2.0へダウングレードするときに実行されます
data/pgroonga.sql
先ほど考えた CREATE FUNCTION
文を追記します。
このファイルはインストール時に実行するSQLなので、追加する他の関数などもすべて記載されています。
...
CREATE FUNCTION pgroonga_list_lagged_indexes()
RETURNS SETOF text AS '
SELECT name FROM pgroonga_wal_status()
WHERE current_block != last_block
OR current_offset != current_offset
OR current_size != last_size
OR EXISTS(
SELECT 1 FROM pg_stat_wal_receiver
WHERE flushed_lsn != latest_end_lsn
);
' LANGUAGE SQL
STRICT
PARALLEL SAFE;
...
data/pgroonga--<現バージョン>--<新バージョン>.sql
先ほど考えた CREATE FUNCTION
文を追記します。
このファイルはアップグレードするときに実行されるSQLなので、「新バージョン」で追加される機能に関するSQLのみが記載されています。
追加する内容は一緒なので割愛。
data/pgroonga--<新バージョン>--<現バージョン>.sql
このファイルはダウングレードするときに実行されるSQLを書くためのものです。
ですので、「新バージョン」で追加した機能を削除して「現バージョン」の状態に戻すためのSQLを書きます。
よって、CREATE FUNCTION
で追加した FUNCTION
を削除するSQLを記載します。
DROP FUNCTION pgroonga_list_lagged_indexes;
まとめ
PostgreSQLの拡張機能に CREATE FUNCTION
で関数を追加する方法を説明してPGroongaに便利関数を追加する方法をまとめました。
今回はSQLのみで実現しました。
次回はC言語による拡張も使った関数の追加方法も説明するのでご期待ください。
補足
この記事で触れた pgroonga_list_lagged_indexes
関数ですが、PostgreSQLのバージョンが14以下の場合に役立ちます。
PostgreSQLのバージョンが15以上の場合は、より便利な PGroongaのWALリソースマネージャー をご利用ください。 ククログでも紹介しています。