1

次のことを行うplpgsql関数を作成したとしましょう。

CREATE OR REPLACE FUNCTION foobar (_foo_data_id bigint)
RETURNS bigint AS $$
BEGIN

    DROP TABLE IF EXISTS tmp_foobar;

    CREATE TEMP TABLE tmp_foobar AS
    SELECT *
    FROM foo_table ft
    WHERE ft.foo_data_id = _foo_data_id;

    -- more SELECT queries on unrelated tables

    -- a final SELECT query that invokes tmp_foobar

END;

最初の質問:

この関数を同時に2回呼び出した場合、の最初の呼び出しがまだ実行されている間に、の2番目の呼び出しでテーブルfoobar()を削除することは可能ですか?tmp_foobarfoobar()

SELECTステートメントがロックを作成することを理解していACCESS SHAREますが、そのロックは、ステートメントが完了するまで、または関数の最後にSELECT暗黙的に示されるまで持続しますか?COMMIT

2番目の質問:

後者が当てはまる場合、ロックが解除されるまで2回目の呼び出しをfoobar()無期限に再試行DROP TABLE IF EXISTS tmp_foobar;しますか、それともある時点で失敗しますか?

4

1 に答える 1

3

関数を同時に 2 回呼び出す場合は、2 つの別々のセッションを使用して呼び出していることを意味します。一時テーブルはセッション間で共有されないため、2 番目のセッションは最初のセッションの tmp_foobar を「認識」せず、相互作用はありません。http://www.postgresql.org/docs/9.2/static/sql-createtable.html#AEN70605 (「一時テーブル」)を参照してください。

ロックはトランザクションが終了するまで存続します (取得方法に関係なく、アドバイザリ ロックは例外ですが、それはあなたが行っていることではありません)。

2 番目の質問は、前提が間違っているため、答える必要はありません。

もう一つ。その一時テーブルにインデックスを作成し、それを分析すると便利な場合があります。これにより、最終的なクエリが高速になる可能性があります。

于 2013-02-08T19:38:57.057 に答える