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

时间:2018-11-21 12:58:42

标签: postgresql temp-tables

我希望我能有效地阐明这一点,所以就这样:

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

现在,由于需要并行运行模型,因此即使在相同的数据库中运行,我也必须确保进程不会冲突。现在,我必须存储记录列表,并按得分变量进行排序,然后对其进行操作。这是查询的开始:

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_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())

尽管我将temptable中的值创建为一个临时表,但该连接与随后查询它的连接完全不同,但我仍收到了该值。我在这里想念什么吗?因为似乎临时表确实可以在连接之间访问。

上面有一个错字,实际上是从conn产生了两个游标,而不是从conn产生了一个游标,而从conn2产生了一个游标。 psycopg2中的各个连接无法访问彼此的临时表,但是从同一连接中产生的游标可以访问。

1 个答案:

答案 0 :(得分:3)

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

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

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

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


不相关,但是:您不能“以排序的方式”存储行。表中的行没有隐式排序顺序。获得有保证的排序顺序的唯一方法是在选择行时使用ORDER BY。您的CREATE TABLE AS语句中的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;
相关问题