2013-02-08 88 views
1

比方說,我已經寫了PLPGSQL函數執行以下操作:表在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; 

第一個問題:

如果我同時兩次調用這個函數,有沒有可能第二次調用foobar()刪除tmp_foobar表,而第一次調用foobar()仍在運行?

我明白SELECT語句創建一個ACCESS SHARE鎖,但該鎖持續到SELECT語句完成或直到在函數結束時隱含COMMIT

第二個問題:

如果是後者,將在foobar()第二次調用無限次地重複嘗試DROP TABLE IF EXISTS tmp_foobar;直到鎖被丟棄還是會在某個時候會失敗?

+0

我不會用這個開始的臨時表。如果單個(大)SELECT更快,我不會感到驚訝。你來自SQL Server的背景嗎? – 2013-02-08 19:45:09

+0

@a_horse_with_no_name我的問題是一個小規模的例子,並不代表我們真實的代碼。我們使用臨時表的原因超出了這個問題的範圍。 – 2013-02-08 20:38:54

回答

3

如果您同時調用兩次函數,則意味着您使用兩個單獨的會話來執行此操作。臨時表不在會話之間共享,因此第二個會話不會從第一個會話「看到」tmp_foobar,並且不會有任何交互。見http://www.postgresql.org/docs/9.2/static/sql-createtable.html#AEN70605(「臨時表」)。

鎖持續到事務結束時(無論你如何獲得這些的;有沒有例外,諮詢鎖,但是這不是你在做什麼)

第二個問題並不需要一個答案,因爲前提是錯誤的。

還有一件事。在你的臨時表上創建索引可能很有用,並對其進行分析;這可能會導致最終查詢速度更快。