2017-07-07 6 views
0

テーブルの行が現在のトランザクションによって作成されているかどうかを調べることは可能ですか?トランザクションはまだアクティブです)?PostgreSQL:現在のトランザクションによって行が作成されたかどうかを調べる

私の使用例:イベントログをデータベースに追加しています。これはplpgsqlトリガーで行われます。イベントテーブルの行は、(event id:serial, event action:text, count:integer:default 1)のようになります。

私の質問の理由:このトランザクションで特定の行が作成されている場合(ほとんどの場合、別のトリガーで)、イベントテーブルに新しい行を作成する代わりにカウントを増やすことができます。

+0

実際の使用例は次のとおりです。あなたの質問は "競争状態"と "完全性の問題"を叫びます。 – spectras

+0

コードが行を作成している場合、作成する行を追跡するのはなぜですか?この方法では、データベースに再度照会することさえせず、コードが直ちにUPDATEを送信することができます。 – spectras

+0

これは、**複数の** plpgsqlトリガーで行われます。だから私は、イベントが作成された行(一時テーブル?タイムスタンプ列?)を追跡することも、より良い方法を見つけ出すこともできます。したがって、私の質問です。 –

答えて

1

あなたはちょうどこのようなログエントリを検索できます。現在のトランザクションに追加または変更されたすべての行を検索します

SELECT ... 
FROM tablename 
WHERE xmin = current_txid() % (2^32)::bigint; 

を。

これは、テーブル全体を順番にスキャンするため、システム列にインデックスを付けることができないため、これを避けることができないという欠点があります。

テーブルに余分な列xidを追加すると、行が挿入または更新されるたびにtxid_current()::bigintが入力されます。このような列は索引付けされ、効率的に検索に使用できます。

SELECT ... 
FROM tablename 
WHERE xid = current_txid(); 
+0

ありがとうございます。 'xid'カラムの追加について考えてみましょう。 –

+0

以下のチェックは偽陽性を避けるためにも有効だと思いますか? 'xid :: text =(txid_current()%(2^32):: bigint):: text;'(あなたの 'xid'カラムを必要とせずに)私はhttps://dba.stackexchange.com/でそれを見つけました質問/ 146315/how-to-compare-xmin-and-txid-current-after-transactions-id-wraparound –

+1

ああ、私は間違いを犯しました。 'current_txid()'は 'xmin'と同じ値を返しません。私は答えを固定し(そして簡略化した)。 –

1

あなたはこのような何か考えるかもしれません:

あなたが言うと呼ばれるPROCでこれをラップすることができます
delete ConnectionCurrentAction where connectionID = pg_backend_pid() 
insert ConnectionCurrentAction(connectionID, currentActionID) 
select pg_backend_pid(), uuid_generate_v4() 

audit_action_begin

注:トランザクションの開始時に

create table ConnectionCurrentAction (
    connectionID int primary key, 
    currentActionID uuid 
) 

、その後に:代わりに、削除を削除して明示的に "アクション"を作成するという要件を適用することができますここに。トランザクションの終わりに

は、 audit_action_end行います

(select currentActionID from ConnectionCurrentAction where connectionID - pg_backend_pid()(

あなたは機能audit_action_current()

あなたにそれをラップすることができます:あなたは、現在のトランザクションを知りたいときはいつでも

delete ConnectionCurrentAction where connectionID = pg_backend_pid() 

現在のアクションで行が作成されたかどうかを識別できるように、currentActionIDをログに入れます。これにより、現在の論理アクションで異なる監査テーブルの行が作成された場所を特定することもできます。

uuidを使用したくない場合は、シーケンスもここで同様に動作します。私はuuidsが好きです。

+1

素晴らしいアイデア!これは非常に便利です。しかし1つの質問:なぜあなたは 'txid_current()'ではなく 'pg_backend_pid()'を使っていますか?その理由があるのか​​どうか疑問に思っています...もう一度ありがとう。 –

+0

優秀な質問です。私は 'txid_current()'について知らなかったので。今私は:-)これであなたは本当にこの答えを必要としません、あなたの監査テーブルにそれをぶら下げてください。 – Ben

+0

もちろん、postgresqlトランザクションとは別の論理的な "アプリケーション"アクションはありません – Ben

関連する問題