#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, включая ее подзапросы, использует один и тот же снимок базы данных, то есть они видят одно и то же состояние базы данных.