# Параметры ОГГ

# Параметр INSERTMISSINGUPDATES в Oracle GoldenGate: как работает и где может пригодиться

Параметр **`INSERTMISSINGUPDATES` (`NOINSERTMISSINGUPDATES`)** управляет поведением процесса **Replicat** в ситуации, когда для операции обновления (UPDATE) не найдена целевая запись. Если параметр включён, **Replicat** вставит новую строку на основе данных из источника; если выключен (значение по умолчанию) – запись отсутствует, возникает ошибка, и дальнейшая судьба транзакции зависит от настройки `REPERROR`.

### Как это работает по документации

**`INSERTMISSINGUPDATES`** следует использовать только тогда, когда исходная база данных гарантированно логирует **все** столбцы строки (даже те, что не изменились). Это необходимо, потому что для вставки новой записи требуются значения всех столбцов, а не только изменённых.

- Если источник передаёт только изменённые столбцы **(сжатый формат обновлений),** параметр всё же может работать при условии, что целевая таблица допускает `NULL` в отсутствующих колонках.
- Если же база данных по умолчанию логирует все столбцы (например, включено дополненное логирование), то для корректной работы **`INSERTMISSINGUPDATES`** необходимо также использовать параметры **`NOCOMPRESSUPDATES`** и **`NOCOMPRESSDELETES`** (если они поддерживаются). В противном случае потребуется **`FETCHOPTIONS MISSINGCOLS`**, чтобы добрать недостающие колонки из источника.

Важно помнить: параметр является таблично-специфичным и действует для всех последующих операторов `MAP`, пока не встретится противоположная директива.

### Дополнительные требования к источнику

Из описания ясно, что для надёжной работы **`INSERTMISSINGUPDATES`** на таблицах источника должно быть включено дополненное логирование всех столбцов:

```sql
ALTER TABLE SCHEME.CUSTOMERS ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
```

<div class="md-code-block md-code-block-light" id="bkmrk-"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>Без этого при обновлении в трейл попадут только изменившиеся колонки, и **Replicat** не сможет сформировать полноценную вставку.

### Неочевидный сценарий использования: заполнение пробелов

Параметр может пригодиться не только для обработки редких ситуаций рассинхронизации, но и для целенаправленного «долива» пропущенных данных. Предположим, в таблице `SCHEME.CUSTOMERS` по какой-то причине образовались пробелы (часть строк отсутствует на приёмнике), мы знаем, что DELETE-операций в этом наборе нет. Мы знаем временной интервал, в котором могли быть пропуски.

Тогда можно выполнить на источнике фиктивный UPDATE, который затронет все потенциально пропущенные строки:

```sql
UPDATE SCHEME.CUSTOMERS SET ID = ID
WHERE DATE_CHANGE BETWEEN TO_DATE('...') AND TO_DATE('...');
```

<div class="md-code-block md-code-block-light" id="bkmrk--1"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>Поскольку условие `ID = ID` не меняет данные, на источнике не происходит реальных изменений, но в трейл всё равно попадут образы строк (**`NOCOMPRESSUPDATES`** за это отвечает). На приёмнике, если строка уже существует, обновление пройдёт без эффекта; если же строки нет, **`INSERTMISSINGUPDATES`** вставит её. Так можно аккуратно засинкать таблицы, без полной перезаливки или использования Веридаты.

### Грабли: порядок операций

Несмотря на заверения оракл, что **Replicat** применяет изменения в том же порядке, что и на источнике, на практике возможны спецэффекты. Например, если после всех обновлений строки она была удалена, но из-за особенностей транспорта или параллельной работы `DELETE` прилетит раньше финального `UPDATE`, то на приёмнике картина может исказиться:

<div class="ds-scroll-area _1210dd7 c03cafe9" id="bkmrk-%D0%98%D1%81%D1%82%D0%BE%D1%87%D0%BD%D0%B8%D0%BA-%D0%9F%D1%80%D0%B8%D1%91%D0%BC%D0%BD%D0%B8%D0%BA-%28%D0%BE"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th>Источник</th><th>Приёмник (ожидание)</th><th>Реальность при нарушении порядка</th></tr></thead><tbody><tr><td>INSERT</td><td>INSERT</td><td>INSERT</td></tr><tr><td>UPDATE</td><td>UPDATE</td><td>UPDATE</td></tr><tr><td>UPDATE</td><td>UPDATE</td><td>UPDATE</td></tr><tr><td>UPDATE</td><td>UPDATE</td><td>DELETE (пришёл раньше последнего UPDATE)</td></tr><tr><td>DELETE</td><td>DELETE</td><td>UPDATE (вставляет пропущенную строку!)</td></tr></tbody></table>

</div>В результате удалённая на источнике строка снова появится на приёмнике из‑за **`INSERTMISSINGUPDATES`**, который вставит её при обработке запоздавшего UPDATE. Поэтому включать параметр'чтоб было' - не стоит.