スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Slony-Iを使用する場合はlastvalは使えない

PostgreSQLのlastvalはセッション内の直前にカウントアップされたシーケンス番号を返します。
シーケンス番号を主キーにしている場合など、insert文を実行後lastvalで主キーを回収することは、PL/pgSQLの関数でよく使うと思います。

CREATE TABLE t_sample (
sample_id bigserial,
sample_name text,
primary key(id)
);

CREATE OR REPLACE FUNCTION insert_sample(p_name text) RETURN bigint AS $$
DECLARE
bigint w_result;
BEGIN
INSERT INTO t_sample(sample_name) VALUES (p_name);
SELECT lastval() INTO w_result;
RETURN w_result;
END;
$$ LANGUAGE plpgsql;

SELECT insert_sample('aaa');

しかし、Slony-Iを使ってt_sampleを同期すると、lastvalは期待している値を返さなくなります。
何故かと言うと、t_sampleのinsertが成功するとSlony-Iのトリガーが起動してSlony-I内で定義されている他のシーケンス番号がカウントアップされてしまうからです。
すると、関数内のlastvalはSlony-I内のシーケンス番号を返してしまいます。

正しい値を返すための対応方法はlastvalの代わりにcurrvalを使います。
currvalは引数に指定したシーケンス名の現在の値を返します。
sample_idのシーケンス名をt_sample_sample_id_seqという名前とすると、関数は以下のようになります。

CREATE OR REPLACE FUNCTION insert_sample(p_name text) RETURN bigint AS $$
DECLARE
bigint w_result;
BEGIN
INSERT INTO t_sample(sample_name) VALUES (p_name);
SELECT currval('t_sample_sample_id_seq') INTO w_result;
RETURN w_result;
END;
$$ LANGUAGE plpgsql;

開発中はSlony-Iを動かさないことが多いと思いますので、開発中にテストしても問題は起こりませんが、実運用でSlony-Iが動き始めると突然問題が発生します。
Slony-Iを使う想定があるなら、lastvalではなくcurrvalを使うようにしましょう。
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。