Выполняется ли ВСТАВКА В с подзапросами как одна транзакция (потокобезопасно)?

#sql #postgresql #transactions #thread-safety #sqltransaction

Вопрос:

У меня есть запрос вставки с подзапросами, который я хочу запустить в базе данных Postgres. Но я не уверен, что запрос с его подзапросами выполняется в одной транзакции.

У нас есть две сущности «конфигурации» и «конфигурации_версий». «Конфигурация» может иметь несколько «конфигураций». У каждого «config_version» есть «rolling_version_id», который не является автоматически увеличиваемым идентификатором (первичным ключом) таблицы. «rolling_version_id» увеличивается на «config_id» и начинается с 1, это означает, что существует уникальное ограничение на config_id rolling_version_id. Вот как я это решил:

 INSERT INTO config_versions(rolling_version_id, config_id, note)
VALUES (
    CASE WHEN EXISTS(SELECT * FROM config_versions WHERE config_id=42) 
    THEN (SELECT MAX(rolling_version_id) 1 FROM config_versions WHERE config_id=42 GROUP BY config_id) ELSE 1 END, 
    42, 
    'SomeNote');
 

Вопрос: Безопасен ли этот поток запросов / Выполняется ли он в одной транзакции?

Комментарии:

1. Один оператор выполняется как одна транзакция, если только не существует распределенной транзакции или явного вызова новой транзакции (например, в какой-либо вложенной функции процедуры). Потому что он должен соответствовать требованиям КИСЛОТЫ.

2. Кроме того, SQL является декларативным, где вы указываете результат, а не способ его вычисления. Он ничего не знает о потоках, потому что они слишком низкоуровневые. Вы можете ознакомиться с этой статьей документа об уровнях изоляции транзакций и их описании.

Ответ №1:

не уверен, что вы подразумеваете под безопасностью, также транзакции sql являются АТОМАРНЫМИ , в любом случае , я не уверен, что ваш запрос выполняется, но вот как вы можете его упростить:

 INSERT INTO config_versions(rolling_version_id, config_id, note)
SELECT coalesce(MAX(rolling_version_id) 1, 1),42,'SomeNote' 
FROM config_versions 
WHERE config_id=42
 

бд<>скрипка <>здесь

Комментарии:

1. Если я добавлю «ГРУППИРОВАТЬ ПО идентификатору конфигурации» в конце, запрос будет выполнен. Но, к сожалению, он ничего не вставляет в случае, если в таблице config_versions не существует config_version с config_id=42. Если в таблице уже есть config_version с идентификатором config_id=42, вставка работает, и идентификатор rolling_version_id увеличивается для новой записи.

2. это работает для меня , проверьте скрипку : db<>скрипка <> здесь

Ответ №2:

Ваш запрос неэффективен, но безопасен (но это не имеет ничего общего с многопоточностью).

Полная инструкция SQL, включая ее подзапросы, использует один и тот же снимок базы данных, то есть они видят одно и то же состояние базы данных.