# Бинарное логирование

Бинарное логирование служит механизмом восстановления данных таблиц [реального времени](../Creating_a_table/Local_tables/Real-time_table.md). При включённом бинарном логировании `searchd` записывает каждую транзакцию в binlog-файл и использует его для восстановления после некорректного завершения работы. При корректном завершении работы данные из RAM-чанов сохраняются на диск, а все binlog-файлы удаляются.

## Включение и отключение бинарного логирования

По умолчанию бинарное логирование включено для защиты целостности данных. В системах Linux стандартное расположение файлов `binlog.*` в [Plain режиме](../Creating_a_table/Local_tables.md#Defining-table-schema-in-config-%28Plain-mode%29) находится в `/var/lib/manticore/data/`. В [RT режиме](../Creating_a_table/Local_tables.md#Online-schema-management-%28RT-mode%29) бинарные логи хранятся в каталоге `<data_dir>/binlog/`, если не указано иное.

### Глобальная конфигурация бинарного логирования

<!-- example binlog_path -->
Для глобального отключения бинарного логирования установите `binlog_path` в пустое значение в конфигурации `searchd`.
Отключение бинарного логирования требует перезапуска демона и повышает риск потери данных при внезапном отключении системы.

<!-- request Example -->
```ini
searchd {
...
    binlog_path = # disable logging
...
```
<!-- end -->

<!-- example binlog_path2 -->
Для задания пользовательского пути можно использовать следующую директиву:

<!-- request Example -->
```ini
searchd {
...
    binlog_path = /var/data
...
```
<!-- end -->

### Конфигурация бинарного логирования на уровне таблиц

<!-- Example binlog0 -->
Для более гибкого управления бинарное логирование можно отключить на уровне таблиц реального времени, установив параметр таблицы `binlog` в значение `0`. Эта опция недоступна для таблиц типа percolate.

<!-- request Example -->
```sql
create table a (id bigint, s string attribute) binlog='0';
```
<!-- end -->

<!-- Example binlog_alter -->
Для существующих RT-таблиц бинарное логирование также можно отключить, изменив параметр `binlog`.

<!-- request Example -->
```sql
alter table FOO binlog='0';
```
<!-- end -->

<!-- Example binlog_alter2 -->
Если бинарное логирование было ранее отключено, его можно вновь включить, установив параметр `binlog` обратно в `1`:

<!-- request Example -->
```sql
alter table FOO binlog='1';
```
<!-- end -->

#### Важные замечания:
* **Зависимость от глобальных настроек**: параметры бинарного логирования на уровне таблиц действуют только если бинарное логирование глобально включено в конфигурации searchd (`binlog_path` не должен быть пустым).
* **Статус бинарного логирования и идентификатор транзакции**: изменение статуса бинарного логирования таблицы вызывает немедленный [принудительный сброс таблицы](../Securing_and_compacting_a_table/Flushing_RAM_chunk_to_disk.md#FLUSH-TABLE). Если выключить бинарное логирование для таблицы, её идентификатор транзакции (TID) меняется на `-1`. Это означает, что бинарное логирование не активно и изменения не отслеживаются. Если же включить бинарное логирование для таблицы, её идентификатор транзакции становится неотрицательным числом (ноль или больше). Это указывает, что изменения таблицы теперь записываются. Проверить идентификатор транзакции можно командой: `SHOW TABLE <name> STATUS`. Значение TID отражает ведется ли запись изменений (неотрицательное число) или нет (`-1`).

## Операции

При включённом бинарном логировании каждое изменение RT-таблицы сохраняется в лог-файл. Если система неожиданно выключается, эти логи автоматически используются при следующем запуске для восстановления всех записанных изменений.

### Размер лога

<!-- Example binlog_max_log_size -->
Во время обычной работы, когда объём записанных данных достигает определённого предела (устанавливаемого параметром `binlog_max_log_size`), начинается новый лог-файл. Старые логи сохраняются до тех пор, пока все изменения в них полностью не обработаются и не сохранятся на диск в виде дискового чанка. Если этот предел установлен в `0`, лог-файлы сохраняются пока система не будет корректно завершена. По умолчанию ограничений на размер файлов нет.

<!-- request Example -->

```ini
searchd {
...
    binlog_max_log_size = 16M
....
```

<!-- end -->

### Лог-файлы

<!-- example binlog_filename_digits -->

Каждый binlog-файл именуется с ведущими нулями, например `binlog.0000`, `binlog.0001` и так далее, обычно с четырьмя цифрами. Количество цифр в номере файла можно изменить настройкой `binlog_filename_digits`. Если количество binlog-файлов превысит вместимость текущего количества цифр, количество цифр будет автоматически увеличено.

**Важно**: для изменения количества цифр необходимо сначала сохранить все данные таблиц и корректно завершить работу системы. Затем удалить старые лог-файлы и перезапустить систему.

<!-- request Example -->
```ini
searchd {
...
    binlog_filename_digits = 6
...
```
<!-- end -->

### Стратегии бинарного логирования

<!-- Example binlog_common -->
Вы можете выбрать один из двух способов управления бинарными лог-файлами с помощью директивы `binlog_common`:
* Отдельный файл на каждую таблицу (по умолчанию, `0`): каждая таблица сохраняет изменения в собственном лог-файле. Такая конфигурация удобна, если у вас много таблиц, обновляющихся в разное время. Это позволяет обновлять таблицы независимо друг от друга. Также если возникает проблема с лог-файлом одной таблицы, это не влияет на другие.
* Один файл для всех таблиц (`1`): все таблицы используют один общий бинарный лог-файл. Этот метод упрощает работу с файлами, так как их меньше. Однако при этом файлы могут дольше храниться, если хотя бы одной таблице нужно сохранить обновления. Также данная настройка может замедлять работу при одновременном обновлении многих таблиц, так как все изменения должны записываться в один файл.

<!-- request binlog_common -->

```ini
searchd {
...
    binlog_common = 1
...
```
<!-- end -->

### Стратегии сброса бинарного лога

<!-- Example binlog_flush -->
Существует четыре различных стратегии сброса бинарного лога, которые регулируются директивой `binlog_flush`:

* `0` - Данные записываются на диск (сбрасываются) каждую секунду, и Manticore инициирует их защиту на диске ([синхронизацию](https://linux.die.net/man/8/sync)) сразу после сброса. Этот метод самый быстрый, но если сервер или компьютер внезапно выйдут из строя, некоторые недавно записанные данные, которые не были защищены, могут быть потеряны.
* `1` - Данные записываются в binlog и синхронизируются сразу после каждой транзакции. Этот метод самый безопасный, так как гарантирует немедленное сохранение каждого изменения, но замедляет запись.
* `2` - Данные записываются после каждой транзакции, а синхронизация инициируется каждую секунду. Этот подход предлагает баланс, записывая данные регулярно и быстро. Однако, в случае сбоя компьютера, часть данных, которые находились в процессе защиты, может не успеть сохраниться. Кроме того, синхронизация может занимать больше одной секунды в зависимости от диска.
* `3` - Похоже на `2`, но также гарантирует, что файл binlog синхронизируется перед закрытием из-за превышения `binlog_max_log_size`.

Режим по умолчанию — `2`, который записывает данные после каждой транзакции и запускает их синхронизацию каждую секунду, балансируя скорость и безопасность.

<!-- request Example -->
```ini
searchd {
...
    binlog_flush = 1 # ultimate safety, low write speed
...
}
```
<!-- end -->

### Поддержка кластерного binlog

<!-- Example binlog_cluster -->
В кластере с использованием Galera важна правильная обработка восстановления узла. Обычно Galera решает проблему рассогласования узла с помощью IST (incremental state transfer — инкрементальная передача состояния), если узел был корректно завершён и его последний номер последовательности (seqno) был правильно сохранён. Однако в случае сбоя, когда seqno не сохранён, Galera инициирует SST (state snapshot transfer — передача снимка состояния), что требует больших ресурсов и может значительно замедлить кластер из-за высокой активности ввода-вывода.

Для решения этой проблемы введена поддержка кластерного binlog. Эта функция расширяет существующую двоичную запись изменений, помогая снизить необходимость SST, позволяя восстанавливающемуся узлу воспроизводить недостающие транзакции из локальных binlog и снова присоединяться к кластеру с корректным seqno.

Кластерный binlog включен по умолчанию для любых операций кластера. Однако его можно отключить, установив переменную окружения:

<!-- request binlog_cluster -->
```bash
MANTICORE_REPLICATION_BINLOG=0
```
<!-- end -->

Эта функция уменьшает время простоя и предотвращает полные передачи данных, сочетая локальную надежность двоичного журнала с возможностями распределённой синхронизации Galera.

### Восстановление

При восстановлении после некорректного отключения binlog воспроизводится, и все зарегистрированные транзакции с момента последнего состоявшегося сохранения на диске восстанавливаются. Транзакции снабжены контрольными суммами, поэтому в случае повреждения файла binlog мусорные данные **не будут** воспроизведены; такая сломанная транзакция будет обнаружена и остановит воспроизведение.

### Сброс RAM-чунк RT

<!-- Example rt_flush_period -->
Интенсивные обновления небольшой таблицы RT, полностью помещающейся в RAM-чунк, могут привести к постоянно растущему binlog, который невозможно удалить до чистого завершения работы. Binlog фактически служит в виде дельты, добавляемой к последнему известному хорошему состоянию на диске, и не может быть удалён, пока RAM-чунк не сохранён. Постоянно растущий binlog нежелателен с точки зрения использования диска и времени восстановления после сбоя. Для решения этой проблемы можно настроить `searchd` на периодический сброс RAM-чунк с помощью директивы `rt_flush_period`. При включённых периодических сбросах `searchd` запускает отдельный поток, проверяющий, нужно ли записать RAM-чунк RT таблицы обратно на диск. Как только это происходит, соответствующие binlog могут быть безопасно (и действительно) удалены.

Период сброса RT по умолчанию установлен на 10 часов.

<!-- request Example -->
```ini
searchd {
...
    rt_flush_period = 3600 # 1 hour
...
}
```
<!-- end -->

Важно отметить, что `rt_flush_period` контролирует лишь частоту проверок. Нет гарантий, что конкретный RAM-чунк будет сохранён. Например, бессмысленно регулярно пересохранять большой RAM-чунк, в который было сделано всего несколько обновлений строк. Manticore автоматически принимает решение о необходимости сброса, используя несколько эвристик.

<!-- proofread -->

