Postgresql 当应用程序可能尝试为独立但同时进行的进程创建临时表时,使用临时表是否安全?

Postgresql 当应用程序可能尝试为独立但同时进行的进程创建临时表时,使用临时表是否安全?,postgresql,temp-tables,Postgresql,Temp Tables,我希望我能有效地表达这一点,所以我想说: 我正在创建一个模型,该模型将由用户在平台上运行,可能同时运行,但每个模型运行都由唯一的整数标识符标记。该模型将执行一系列PostgreSQL查询,并最终在此处写入结果 现在,由于模型运行需要并行化,我必须确保进程不会冲突,尽管它们运行在同一个数据库中。我现在必须存储一个记录列表,按分数变量排序,然后对它们进行操作。这是查询的开始: DO $$ DECLARE row RECORD; BEGIN DROP TABLE IF EXISTS ranked_c

我希望我能有效地表达这一点,所以我想说:

我正在创建一个模型,该模型将由用户在平台上运行,可能同时运行,但每个模型运行都由唯一的整数标识符标记。该模型将执行一系列PostgreSQL查询,并最终在此处写入结果

现在,由于模型运行需要并行化,我必须确保进程不会冲突,尽管它们运行在同一个数据库中。我现在必须存储一个记录列表,按分数变量排序,然后对它们进行操作。这是查询的开始:

DO
$$
DECLARE row RECORD;
BEGIN

DROP TABLE IF EXISTS ranked_clusters;
CREATE TEMP TABLE ranked_clusters AS (
    SELECT
        pl.cluster_id AS c_id,
        SUM(pl.total_area) AS cluster_score
    FROM
        emob.parking_lots AS pl
    WHERE
        pl.cluster_id IS NOT NULL
        AND
        run_id = 2005149
    GROUP BY
        pl.cluster_id
    ORDER BY
        cluster_score DESC
);

FOR row IN SELECT c_id FROM ranked_clusters LOOP
    RAISE NOTICE 'Cluster %', row.c_id;
END LOOP;

END;
$$ LANGUAGE plpgsql;
因此,我创建了一个名为
ranked_clusters
的临时表,然后对其进行迭代,目前只记录每个记录的标识符

我一直小心地只根据
run\u id
值等于某个数字的记录构建此列表,因此将忽略来自相同来源但数字不同的数据

然而,我担心的是,一个同时进行的进程也会创建自己的
ranked_clusters
临时表,这将与第一个表冲突,从而使结果无效

所以我的问题本质上是这样的:临时表是否只对创建它们的会话可见(或者对Python中的游标对象可见)?这样使用临时表安全吗

我问这个问题的主要原因是,我看到这些所谓的“临时”表似乎在我在PgAdmin III中执行查询后仍然存在,并且查询在下一次执行时失败,因为该表已经存在。这让我很烦恼,因为似乎这些表在其生命周期内实际上是全局可访问的,因此在同时运行时会引入冲突的可能性

感谢@a_horse_with_no_name的解释,但我还不确信它是安全的,因为我已经能够执行以下代码:

import psycopg2 as pg2

conn = pg2.connect(dbname=CONFIG["GEODB_NAME"],
                       user=CONFIG["GEODB_USER"],
                       password=CONFIG["GEODB_PASS"],
                       host=CONFIG["GEODB_HOST"],
                       port=CONFIG["GEODB_PORT"])
conn.autocommit = True
cur = conn.cursor()

conn2 = pg2.connect(dbname=CONFIG["GEODB_NAME"],
                    user=CONFIG["GEODB_USER"],
                    password=CONFIG["GEODB_PASS"],
                    host=CONFIG["GEODB_HOST"],
                    port=CONFIG["GEODB_PORT"])
conn2.autocommit = True
cur2 = conn.cursor()

    cur.execute("CREATE TEMPORARY TABLE temptable (tempcol INTEGER); INSERT INTO temptable VALUES (0);")
    cur2.execute("SELECT tempcol FROM temptable;")
    print(cur2.fetchall())
我在
attreable
中接收到这个值,尽管它是作为一个临时表在一个完全不同的连接中创建的,而这个连接后来查询它。我是不是遗漏了什么?因为在连接之间似乎确实可以访问临时表


上面有一个输入错误,两个游标实际上都是从
conn
生成的,而不是一个从
conn
生成,另一个从
conn2
生成。psycopg2中的各个连接无法访问彼此的临时表,但从同一连接生成的游标可以访问。临时表仅对创建它们的会话(=连接)可见。即使两个会话创建同一个表,它们也不会相互干扰

会话断开连接时,会自动删除临时表

如果要在事务结束时自动删除它们,请在创建表时使用提交时的
ON COMMIT DROP
选项

所以答案是:是的,这是安全的


不相关,但是:不能“按排序方式”存储行。表中的行没有隐式排序顺序。获得保证排序顺序的唯一方法是在选择行时使用
order BY
。CREATETABLEAS语句中的
order by
是非常无用的

如果必须依赖行的排序顺序,唯一安全的方法是使用SELECT语句:

FOR row IN SELECT c_id FROM ranked_clusters ORDER BY cluster_score 
LOOP
    RAISE NOTICE 'Cluster %', row.c_id;
END LOOP;
对于中的行,从按聚类分数排序的聚类中选择c\U id
环
提出通知“群集%”,第c_id行;

端环临时表仅对创建它们的会话(=连接)可见。即使两个会话创建同一个表,它们也不会相互干扰

会话断开连接时,会自动删除临时表

如果要在事务结束时自动删除它们,请在创建表时使用提交时的
ON COMMIT DROP
选项

所以答案是:是的,这是安全的


不相关,但是:不能“按排序方式”存储行。表中的行没有隐式排序顺序。获得保证排序顺序的唯一方法是在选择行时使用
order BY
。CREATETABLEAS语句中的
order by
是非常无用的

如果必须依赖行的排序顺序,唯一安全的方法是使用SELECT语句:

FOR row IN SELECT c_id FROM ranked_clusters ORDER BY cluster_score 
LOOP
    RAISE NOTICE 'Cluster %', row.c_id;
END LOOP;
对于中的行,从按聚类分数排序的聚类中选择c\U id
环
提出通知“群集%”,第c_id行;

端环+1。我建议在使用连接池时使用“提交时删除”以避免临时表保留。感谢您的回答,但我在问题中添加了更多内容,因为我似乎实际上可以使用两个不同的连接访问临时表Python@1saac:当然可以,如果您在两个不同的连接中创建它们。表中的数据将特定于会话。您将看到,如果在两个会话的两个表中插入不同的值,但在我的示例中,我插入的数据仅来自第一个连接,而第二个连接能够查询相同的数据-临时表不应该只存在于第一个连接的范围内吗?@1saac我不知道Python,也许它实际上并没有创建两个连接。但我知道,在一个会话中插入的数据在其他(物理不同的)会话中是不可见的。对
psql
+1的两个实例尝试相同的方法。我建议在使用连接池时使用“ON COMMIT DROP”以避免临时表保留。谢谢你的回答,但我在问题中添加了更多内容,因为看起来我实际上可以使用两个不同的连接访问临时表