Безопасно ли использовать временные таблицы, когда приложение может попытаться создать их для независимых, но одновременных процессов? - PullRequest
0 голосов
/ 21 ноября 2018

Я надеюсь, что смогу сформулировать это эффективно, так что вот так:

Я создаю модель, которая будет запускаться на платформе пользователями, возможно, одновременно, но каждый запуск модели отмеченуникальный целочисленный идентификатор.Эта модель выполнит серию запросов PostgreSQL и в конечном итоге запишет результат.

Теперь, из-за необходимости распараллеливания прогонов модели, я должен убедиться, что процессы не столкнутся, несмотря на то, что они работают в одной базе данных.,Сейчас я нахожусь в точке, где мне нужно сохранить список записей, отсортированных по переменной Score, и затем работать с ними.Это начало запроса:

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 голосов
/ 21 ноября 2018

Временные таблицы видны только сеансу (= соединение), который их создал.Даже если две сессии создают одну и ту же таблицу, они не будут мешать друг другу.

Временные таблицы удаляются автоматически при отключении сеанса.

Если вы хотите автоматически удалить их притранзакция заканчивается, используйте опцию ON COMMIT DROP при создании таблицы.

Итак, ответ: да, это безопасно.


Не связано, но: вы не можете хранить строки"в отсортированном виде".Строки в таблице не имеют неявного порядка сортировки.Единственный способ получить гарантированный порядок сортировки - использовать ORDER BY при выборе строк.order by, который является частью вашего оператора CREATE TABLE AS, в значительной степени бесполезен.

Если вам нужно полагаться на порядок сортировки строк, единственный безопасный способ сделать это - воспользоваться оператором SELECT:

FOR row IN SELECT c_id FROM ranked_clusters <b>ORDER BY cluster_score </b>
LOOP
    RAISE NOTICE 'Cluster %', row.c_id;
END LOOP;
...