Логирование TLI
Логирование инвалидации блокировок транзакций (TLI) позволяет установить, у какого запроса были сломаны блокировки (жертва) и какой запрос их сломал (нарушитель).
Включение логирования
Для получения детальных логов о конфликтах блокировок установите уровень INFO (числовое значение 6) для компонента TLI.
Добавьте в конфигурацию кластера:
log_config:
entry:
- component: "TLI"
level: 6 # INFO
Параметр log_config поддерживает динамическое обновление без перезапуска узлов.
После включения сервер записывает логи при каждой сломанной блокировке, а VictimQuerySpanId начинает появляться в сообщении об ошибке SDK.
Примечание
Базовый размер лога для одного TLI-события составляет 10–20 КБ. Фактический объем зависит от размера текста логируемых запросов (виновника и жертвы) и транзакций, частью которых они являются, поскольку все эти данные записываются в лог.
Если конфликты редки, нагрузка на логирование незначительна. При высокой частоте TLI суммарный объём логов может быть существенным.
Чтобы исключить таблицы с ожидаемыми конфликтами из TLI-диагностики, используйте параметр tli_config.ignored_table_regexes.
Структура логов
Когда происходит TLI, сервер записывает в лог записи от каждого компонента (DataShard или SessionActor) для каждой из сторон конфликта (жертвы или нарушителя). Количество записей зависит от количества запросов в транзакциях.
Пример сценария:
Устанавливается две сессии к СУБД: жертва и нарушитель.
| Время | QuerySpanId | Роль | Запрос |
|---|---|---|---|
| T1 | 1111111111111111 |
Жертва | SELECT * FROM Orders WHERE OrderId = 42 (устанавливает блокировку) |
| T2 | 2222222222222222 |
Нарушитель | UPDATE Orders SET Status = 'done' WHERE OrderId = 42 (ломает блокировку) |
| T3 | 3333333333333333 |
Жертва | UPDATE Orders SET Amount = 100 WHERE OrderId = 42 (коммит — падает) |
Примечание
В приводимых далее примерах содержимого логов порядок следования отдельных полей внутри записей может отличаться.
Лог нарушителя (DataShard):
component=DataShard tabletId=<tablet-id> message="Write transaction broke other locks" breakerQuerySpanId=2222222222222222 victimQuerySpanId=1111111111111111
Лог нарушителя (SessionActor):
component=SessionActor message="Query had broken other locks" breakerTxSpanId=2222222222222222 querySpanId=2222222222222222 queryText="UPDATE Orders SET Status = 'done' WHERE OrderId = 42"
Лог жертвы (DataShard):
component=DataShard tabletId=<tablet-id> message="Write transaction was a victim of broken locks" victimQuerySpanId=1111111111111111
Лог жертвы (SessionActor):
В этом примере SessionActor записывает две записи — по одной на каждый запрос транзакции-жертвы:
component=SessionActor message="Query was a victim of broken locks" victimTxSpanId=1111111111111111 querySpanId=1111111111111111 queryText="SELECT * FROM Orders WHERE OrderId = 42"
component=SessionActor message="Query was a victim of broken locks" victimTxSpanId=1111111111111111 querySpanId=3333333333333333 queryText="UPDATE Orders SET Amount = 100 WHERE OrderId = 42"
Поля логов
| Поле | Описание | Где встречается |
|---|---|---|
component |
Источник записи: DataShard или SessionActor |
Все логи TLI |
message |
Тип события (см. примеры выше) | Все логи TLI |
tabletId |
Идентификатор таблета DataShard | Логи DataShard |
victimQuerySpanId |
Идентификатор запроса, чьи блокировки были сломаны | Логи жертвы DataShard, логи нарушителя DataShard |
breakerQuerySpanId |
Идентификатор запроса, который сломал блокировки | Логи нарушителя DataShard |
victimTxSpanId |
Идентификатор запроса-жертвы, чьи блокировки были сломаны. Совпадает с victimQuerySpanId в логах DataShard. | Логи жертвы SessionActor |
breakerTxSpanId |
Идентификатор запроса-нарушителя, который сломал блокировки. Совпадает с breakerQuerySpanId в логах DataShard. | Логи нарушителя SessionActor |
querySpanId |
Идентификатор конкретного запроса в записи SessionActor | Логи SessionActor |
queryText |
SQL конкретного запроса в записи SessionActor | Логи SessionActor |
Анализ логов
По VictimQuerySpanId из сообщения об ошибке SDK можно найти все связанные события:
-
Поиск идентификатора запроса-жертвы: в логе жертвы поле
victimQuerySpanIdсодержит идентификатор SELECT-запроса, который установил сломанные блокировки. -
Поиск текста запроса-жертвы: в логе жертвы есть запись, у которой
victimTxSpanIdсовпадает сquerySpanId. ПолеqueryTextэтой записи содержит текст SELECT-запроса, который установил сломанные блокировки. -
Поиск идентификатора запроса-нарушителя: в логе нарушителя DataShard есть запись, у которой поле
victimQuerySpanIdсодержит то же самое значение (идентификатор запроса-жертвы). Из этой записи берётся значениеbreakerQuerySpanId, которое является идентификатором запроса-нарушителя. -
Поиск текста запроса-нарушителя: в логе нарушителя есть запись, у которой
breakerTxSpanIdсодержит идентификатор запроса-нарушителя и в то же время совпадает сquerySpanId. ПолеqueryTextэтой записи содержит текст запроса-нарушителя. -
Получение полного контекста транзакций: все записи SessionActor с одним и тем же
victimTxSpanIdсодержат сведения о запросах транзакции-жертвы. Аналогично, все записи SessionActor с одним и тем жеbreakerTxSpanIdсодержат сведения о запросах транзакции-нарушителя.
Утилита find_tli_chain
Для автоматического анализа логов TLI в репозитории YDB есть утилита find_tli_chain.py.
Данная утилита принимает на вход параметры:
VictimQuerySpanId- идентификатор сломанного запроса из сообщения об ошибке SDK;LogFile- имя лог-файла для анализа логов.
Подразумевается, что логирование TLI было предварительно включено в конфигурации, лог файлы собраны с узлов базы данных и объединены в один файл.
python3 find_tli_chain.py <VictimQuerySpanId> <LogFile>
Пример:
python3 find_tli_chain.py 1111111111111111 ydb.log
================================================
TLI Chain
================================================
VictimQuerySpanId: 1111111111111111
VictimQueryText: SELECT * FROM Orders WHERE OrderId = 42
BreakerQuerySpanId: 2222222222222222
BreakerQueryText: UPDATE Orders SET Status = 'done' WHERE OrderId = 42
================================================
VictimTx
================================================
SELECT * FROM Orders WHERE OrderId = 42
UPDATE Orders SET Amount = 100 WHERE OrderId = 42
================================================
BreakerTx
================================================
UPDATE Orders SET Status = 'done' WHERE OrderId = 42
Утилита выводит:
- TLI Chain —
VictimQuerySpanId,VictimQueryText,BreakerQuerySpanId,BreakerQueryText; - VictimTx — все запросы транзакции-жертвы;
- BreakerTx — все запросы транзакции-нарушителя.
Дополнительные параметры:
| Параметр | Описание |
|---|---|
--window-sec N |
Временное окно поиска вокруг события (по умолчанию 10 с) |
--no-color |
Отключить цветной вывод |
Примечание
Утилита корректно обрабатывает несортированные и смешанные лог-файлы: фильтрация основана на значениях временных меток, а не на позициях строк.