# Транзакции

В Picodata поддерживаются [транзакции] — блоки команд. В рамках
транзакции пользователь может выполнить несколько SQL-запросов атомарно
— так, как если бы это был единый запрос. Для транзакционных запросов
действуют [ограничения](#limitations).

[транзакции]: ../../overview/glossary.md#transactions
[бакет]: ../../overview/glossary.md#bucket

## Структура {: #structure }

Транзакционный блок представляет собой запрос вида `DO $$ BEGIN ... END $$;`,
внутри которого можно поместить набор вложенных запросов. Такой блок
функционально является неименованной процедурой.

## Поддерживаемые команды исполнения {: #supported_statements }

На данный момент для транзакционных блоков поддерживаются следующие
команды исполнения:

- `<DML>` — выполнить вложенный [DML]-запрос (см. ограничения
  [ниже](#limitations)).
- `RETURN QUERY <DQL>` — выполнить вложенный запрос и отобразить результат
  выполнения (используется для [DQL]-запросов).

## Пример использования {: #usage_example }

```sql
DO $$ BEGIN
  RETURN QUERY SELECT item FROM warehouse WHERE id = 2;
  UPDATE warehouse SET item = 'grills' where id = 2;
END $$;
```

## Ограничения {: #limitations }

Поддержка транзакционного выполнения команд в Picodata имеет
ограничения:

- В рамках одной транзакции нельзя обращаться к более чем одному
  [движку хранения](../../overview/glossary.md#db_engine)
- Все запросы к [шардированным] таблицам внутри блока должны
  затрагивать только один [бакет]. При нарушении этого условия
  Picodata вернет пользователю ошибку. В будущем появится поддержка
  команды `EXPLAIN` для транзакционных блоков, с помощью которой
  можно будет наглядно увидеть затронутые бакеты.
- Поддерживаются только запросы, не требующие [перемещения данных].
  Иными словами, в текущей реализации транзакции должны быть выполнимы
  в рамках одного узла Picodata. Глобальные транзакции, затрагивающие
  данные на нескольких узлах, не поддерживаются.
- Для глобальных таблиц поддерживаются только читающие запросы ([DQL]),
  но не модифицирующие ([DML]).
- Читающие команды в блоке должны располагаться строго до
  модифицирующих: то есть, все `RETURN QUERY SELECT ...` должны идти до
  [DML] и дальше уже появиться не могут.

[перемещения данных]: explain.md#data_motion_types
[шардированным]: ../../overview/glossary.md#sharding
[DML]: dml.md
[DQL]: dql.md
