web-dev-qa-db-ja.com

同じコミットされていないトランザクションに挿入されたデータを選択できますか?

多分これは馬鹿げた初心者の質問ですが、私はどこにも答えを見つけることができません。どこでも私が読んだTransaction Isolationは、並行トランザクション内のデータの可視性を解決します。私の懸念は、単一のトランザクション内の動作です。

トランザクションを開始し、データを挿入すると、それらをすぐに選択できるようになりますか?それでも、同じ、まだコミットされていないトランザクション内ですか?はいの場合、この動作は、同時トランザクションの場合の前述のトランザクション分離と同様の方法で変更できますか?

具体的には、PostgreSQL 9.4をターゲットにしています。

23
NumberFour

はい
同じトランザクション内で行ったすべてのことは、同じトランザクション内の後続のコマンドに表示されます。コミットされるまで、他のトランザクションに対しては行わないでください。これは、すべての 分離レベル に当てはまります。ただし、Read uncommittedを除き、「ダーティリード」が可能です(ただし、質問自体には影響しません)。

TransactionId sに基づいて MVCCモデル(Multiversion Concurrency Control) を使用して実装され、すべてのテーブル行の相対的な経過時間と可視性を決定します。同じトランザクションで書き込まれたすべての新しい行バージョンは同じxminを取得し、「同時に」発生したと見なされます。

同じコマンド内に複数の CTEs(Common Table Expression) のコーナーケースがあります。それらは順次実行されると考えるかもしれませんが、一方のCTEが他方を参照しない限り、それらのシーケンスは任意です。そして、それらすべてが、クエリの最初から同じスナップショットを参照します。そのため、同じクエリの複数のCTEで同じ行を複数回UPDATEすることはできません。あいまいになります。

例:

高度な例:

18

やってみよう :

CREATE OR REPLACE FUNCTION public.sp_get_user()
 RETURNS json
 LANGUAGE plpgsql
AS $function$BEGIN

INSERT INTO users (name, password) VALUES ('deadeye', 'test');
RETURN row_to_json(row) FROM (SELECT name, password FROM users WHERE name = 'deadeye') row;

END;$function$

では、テストしてみましょう。

SELECT sp_get_user();
{"name":"deadeye","password":"test"}

できます !アーウィンが言ったように、トランザクションで行われたすべてがトランザクション内に表示されます。分離は、異なるスレッド間でのみ行われます。

4
DeadEye