2012-02-14 2 views
0

私はPostgreSQL 9.0.5を使用しています。定期的にテーブルから新しく作成された行を読み取り、その値を時間別データを含むサマリーテーブルに蓄積するcronジョブがあります。コミットされる前のすべての行が最後のPostresqlシリアルIDを取得する方法は?

コミットする最新のID(シリアル)とコミットする前にすべての行を取得する必要があります。

この場合、currvalを挿入するトランザクションが他のものより早くコミットする可能性があるため、currval関数はこの場合正しい値を与えません。 SELECT文を使用すると、Idカラムはまだコミットされていない行があるため、継続していないことがわかります。

Here is some sample code I have used to test: 
--test race condition 
create table mydata(id serial,val int); 

--run in thread 1 
create or replace function insert_delay() returns void as $$ 
begin 
insert into mydata(val) values (1); 
perform pg_sleep(60); 
end; 
$$ language 'plpgsql'; 

--run in thread 2 
create or replace function insert_ok() returns void as $$ 
begin 
insert into mydata(val) values (2); 
end; 
$$ language 'plpgsql'; 

--run in thread 3 
mytest=# select * from mydata; --SHOULD HAVE SEEN id = 1 and 2; 
id | val 
----+----- 
    2 | 2 
(1 row) 

私も以下のようないくつかのステートメントを試してみました。

select max(id) from mydata age(xmin) >= age(txid_snapshot_xmin(txid_current_snapshot())::text::xid); 

しかし、(大量のトランザクションを実行している)の生産ラインでは、返された最大値(ID)が前方に(でも、すべての忙しいトランザクションが終了している)に移動しません。だからこれはどちらもうまくいかない。

+0

トリガーでサマリーテーブルをリアルタイムで作成させることができない理由はありますか? –

+0

1.タイムスタンプの列でこれを行います。 2.私はあなたが何をしたいのか完全に理解していませんが、あなたがそれを見ていない場合に備えて、トランザクション分離を使って読み取りレベルを制御することができます:http://www.postgresql.org/docs/9.1/static /transaction-iso.htmlので、他のコミットされていないトランザクションを「見る」可能性があります – vasquez

+0

これは基本的に同じ問題です(別の角度から質問していますが)。http://stackoverflow.com/questions/9226322/setting- timestamp-inside-transaction/9226786それ自体はhttp://stackoverflow.com/questions/1914675/reading-only-new-rows-from-a-log-like-table-in-a-databaseのようなものです。 – araqnid

答えて

0

これを直接行うのは本当に良い方法ではありません。私は最良の選択肢は、実際にはトランザクションコミットを切り捨てる一時テーブルを作成することと、そのテーブルにそのようなテーブルを挿入するトリガーだと思います。次に、tempテーブルから値を参照することができます。

関連する問題