# Как выполнить несколько записей в транзакции

> Руководство по транзакционной записи

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

## Предварительные условия {#prerequisites}

* Установите [`etcd` и `etcdctl`](/ru/docs/etcd/install/).
* Работающий кластер `etcd`.

## Терминология {#terminology}

Ниже определены ключевые термины, используемые в [примере](#example).

| Термин | Определение |
| --- | --- |
| [etcdctl](https://github.com/etcd-io/etcd/blob/main/etcdctl/README.md#etcdctl) | Инструмент командной строки для взаимодействия с сервером etcd. |
| Команда [`txn`](https://github.com/etcd-io/etcd/blob/main/etcdctl/README.md#txn-options) | Название команды `txn` сокращает слово «transaction». Она читает несколько запросов etcd из стандартного ввода и применяет их как одну атомарную транзакцию. Транзакция состоит из списка условий, списка запросов, выполняемых при истинности всех условий, и списка запросов, выполняемых при ложности любого условия. Дополнительные сведения приведены в разделе [команд etcdctl для ключей и значений](https://github.com/etcd-io/etcd/blob/main/etcdctl/README.md#key-value-commands).|
| `compare` | Секция `compare` в транзакции (`txn`) выполняет условную проверку и определяет, следует ли выполнять операции транзакции. Изменения применяются только тогда, когда текущее состояние хранилища ключей и значений соответствует ожидаемым условиям. Это сохраняет согласованность данных и предотвращает конфликты при параллельной работе. Структура команды показана ниже в разделе [Выполнение транзакции](#2-perform-a-transaction).|

## Транзакции {#transactions}

Команда `txn` обрабатывает все запросы в одной транзакции:

```bash
etcdctl txn --help
```

Транзакции etcd позволяют атомарно выполнить несколько операций: либо применяются все операции, либо не применяется ни одна. Это необходимо для сохранения согласованности данных при связанных обновлениях. Подробнее см. в [документации API](/ru/docs/etcd/learning/api/#transaction).

### Пример {#example}

Рассмотрим обновление адреса электронной почты и номера телефона пользователя в одной транзакции. Оба изменения будут применены совместно.

![05_etcdctl_transaction_2024101213](/docs/etcd/tasks/img/transactional-write.gif)

#### 0. Используемые переменные и флаги {#0-variables-and-flags-used}

| Переменные |
| :--- |
| `/users/{<user_id>/email` : ключ etcd, представляющий адрес электронной почты пользователя.|
| `/users/<user_id>/phone` : ключ etcd, представляющий номер телефона пользователя.|
| **Флаги** |
| [`--interactive`](https://github.com/etcd-io/etcd/blob/main/etcdctl/README.md#options-3) : флаг, разрешающий вводить данные транзакции вручную|

#### 1. Создание исходных данных {#1-set-up-initial-data}

Сначала создайте пользователя с исходными данными.

   ```shell
   etcdctl put /users/12345/email "old.address@johndoe.com"
   etcdctl put /users/12345/phone "123-456-7890"
   ```

#### 2. Выполнение транзакции {#2-perform-a-transaction}

Обновите адрес электронной почты и номер телефона пользователя в одной транзакции.

   ```shell
   etcdctl txn --interactive

   compares:
   value("/users/12345/email") = "old.address@johndoe.com"

   success requests (get, put, delete):
   put /users/12345/email "new.address@johndoe.com"
   put /users/12345/phone "098-765-4321"

   failure requests (get, put, delete):
   get /users/12345/email
   ```

* **Сравнение**: проверьте, что текущий адрес равен «<old.address@johndoe.com>». Транзакция продолжится только при ожидаемом состоянии данных.
* **Успех**: если сравнение истинно, обновите и адрес электронной почты, и номер телефона.
* **Неудача**: если сравнение ложно, получите текущий адрес, чтобы выяснить, почему транзакция не была выполнена.

### Важные соображения {#important-considerations}

* **Атомарность**: транзакция гарантирует совместное обновление адреса электронной почты и номера телефона. Если исходное условие сравнения не выполнено, ни одно обновление не применяется.
* **Согласованность**: транзакции сохраняют согласованность данных, особенно при нескольких связанных обновлениях.
* **Не записывайте один ключ несколько раз**: не присваивайте одному ключу несколько значений в одной транзакции, поскольку это может привести к неожиданным результатам. Каждый ключ следует обновлять только один раз за транзакцию.
