2013-02-08 57 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(“临时表”)。

锁持续到事务结束时(无论你如何获得这些的;有没有例外,咨询锁,但是这不是你在做什么)

第二个问题并不需要一个答案,因为前提是错误的。

还有一件事。在你的临时表上创建索引可能很有用,并对其进行分析;这可能会导致最终查询速度更快。