FAQ
Q: При работе с динамическими таблицами из Python API или C++ API получаю ошибку «Sticky transaction 1935-3cb03-4040001-e8723e5a is not found», что делать?
A: Ответ зависит от того, как используются транзакции. Если используется мастерная транзакция, то это бессмысленное действие, в таком случае необходимо задавать запрос вне транзакции, для этого можно либо создать отдельный клиент, либо явно указать, что запускаться под нулевой транзакций (with client.Transaction(transaction_id="0-0-0-0"): ...
).
Полноценное использование таблетных транзакций в Python API возможно только через RPC-proxy (yt.config['backend'] = 'rpc'
). Использование таблетных транзакций через HTTP невозможно в текущей реализации.
Q: При записи в динамическую таблицу возникает ошибка «Node is out of tablet memory; all writes disabled» или «Active store is overflown, all writes disabled». Что она означает и как с ней бороться?
A: Ошибка возникает, когда на узле кластера заканчивается память для хранения данных, не записанных на диск. Входной поток данных слишком велик, узел кластера не успевает выполнять сжатие и запись на диск. Запросы с подобными ошибками необходимо повторять, возможно с увеличивающейся задержкой. Если ошибка возникает постоянно, то это может означать (помимо случаев нештатной работы), что либо отдельные таблеты перегружены нагрузкой по записи, либо мощности кластера недостаточно, чтобы справиться с данной нагрузкой. Также может помочь увеличение количества таблетов в таблице (команда reshard-table
).
Q: Что значит сообщение «Too many overlapping stores»? Что делать?
A: Данное сообщение об ошибке значит, что структура таблета такова, что покрытие сторами (dynamic store) обслуживаемого таблетом интервала ключей слишком плотное. Плотное покрытие сторами ведет к деградации производительности чтения, поэтому в данной ситуации включается защитный механизм, препятствующий записи новых данных. Постепенно фоновые процессы компактификации и партицирования должны нормализовать структуру таблета; если этого не происходит, то, возможно, кластер не справляется с нагрузкой.
Q: При запросе в динамическую таблицу получаю ошибку «Maximum block size limit violated»
A: В запросе участвует динамическая таблица, когда-то сконвертированная из статической. При этом не был указан параметр block_size
. При получении подобной ошибки убедитесь, что выполняете все указания из раздела, посвящённого конвертации статической таблицы в динамическую. Если размер блока получается большим, то следует увеличить max_unversioned_block_size
до 32 мегабайт и перемонтировать таблицу. Так может быть, если в ячейках таблицы хранятся больше бинарные данные, а они целиком попадают в один блок.
Q: При запросе в динамическую таблицу получаю ошибку «Too many overlapping stores in tablet»
A: Скорее всего, таблет не справляется с потоком записи — новые чанки не успевают компактифицироваться. Следует проверить, пошардирована ли таблица на достаточное число таблетов. При записи данных в пустую таблицу стоит отключить автошардирование, поскольку маленькие таблеты будут объединяться в один.
Q: При запросе в динамическую таблицу получаю ошибку «Active store is overflown, all writes disabled»
A: Таблет не справляется с потоком записи — либо не успевает сбрасывать данные на диск, либо по каким-то причинам не может этого сделать. Следует проверить, нет ли ошибок в атрибуте таблицы @tablet_errors
, если нет, то, аналогично предыдущему пункту, проверить шардирование.
Q: При запросе в динамическую таблицу получаю ошибку «Too many stores in tablet, all writes disabled»
A: Слишком большой таблет. Необходимо добиться, того чтобы у таблицы стало больше таблетов. Обратите внимание, что автошардирование ограничивает число таблетов числом селлов, умноженном на значение параметра tablet_balancer_config/tablet_to_cell_ratio
.
Q: При запросе в динамическую таблицу получаю ошибку «Tablet ... is not known»
A: Клиент отправил запрос на узел кластера, таблет на котором уже не обслуживается. Как правило, такое происходит в результате автоматической балансировки таблетов или перезапуска узлов кластера. Необходимо повторно отправить запрос, ошибка исчезнет сама после обновления кеша, либо отключать балансировку.
Q: При запросе в динамическую таблицу получаю ошибку «Service is not known»
A: Клиент отправил запрос на узел кластера, таблет-селл на котором уже не обслуживается. Как правило, такое происходит при перебалансировке селлов. Необходимо повторно отправить запрос, ошибка исчезнет сама после обновления кеша.
Q: При запросе в динамическую таблицу получаю ошибку «Chunk data is not preloaded yet»
A: Сообщение характерно для таблицы с параметром in_memory_mode
, отличным от none
. Такая таблица в смонтированном состоянии всегда находится в памяти. Для того чтобы читать из такой таблицы, все данные должны быть загружены в память. Если таблица была только что смонтирована, таблет был перемещен в другой селл, или был перезапуск процесса YTsaurus, то данных в памяти нет, и возникает подобная ошибка. Необходимо подождать загрузки данных в память фоновым процессом.
Q: В tablet_errors вижу ошибку «Too many write timestamps in a versioned row» или «Too many delete timestamps in a versioned row»
A: В сортированных динамических таблицах одновременно хранится много версий одного и того же значения. В lookup формате у каждого ключа может быть не более 2^16 версий. В качестве простого решения можно использовать поколоночный формат (@optimize_for = scan
). На практике такое большое число версий не нужно, они возникают вследствие неправильной конфигурации или программной ошибки. Например, при указании atomicity=none
можно обновлять один и тот же ключ таблицы с огромной частотой (в данном режиме не происходит блокировки строк и транзакции с пересекающимся диапазоном времени могут обновлять один и тот же ключ). Так делать не рекомендуется. Если же запись большого числа версий вызвана продуктовой необходимостью, например, частые записи дельт в агрегирующих колонках, стоит выставить атрибут таблицы @merge_rows_on_flush=%true
и корректно настроить удаление данных по TTL, чтобы при флаше в чанк записывалось только небольшое число реально необходимых версий.
Q: При запросе Select Rows получаю ошибку 'Maximum expression depth exceeded'
A: Такая ошибка возникает, если глубина дерева разбора выражения получается слишком большой. Как правило, такое происходит при написании выражений вида
FROM [...] WHERE (id1="a" AND id2="b") OR (id1="c" AND id2="d") OR ... <несколько тысяч условий>
Вместо этого их нужно задавать в форме FROM [...] WHERE (id1, id2) IN (("a", "b"), ("c", "b"), ...)
С первым вариантом есть несколько проблем. Дело в том, что запросы компилируются в машинный код. Машинный код для запросов кешируются так, что ключом служит структура запроса без учета констант.
- В первом случае при увеличении количества условий структура запроса будет постоянно меняться. Будет кодогенерация на каждый запрос.
- Первый запрос будет порождать очень большое количество кода.
- Компиляция запроса будет очень медленной.
- Первый случай будет работать просто проверкой всех условий. Никакой трансформации в более сложный алгоритм там не предусмотрено.
- Кроме этого, если колонки ключевые, для них выводятся диапазоны чтения, чтобы читать только нужные данные. Алгоритм вывода диапазонов чтения будет более оптимально работать для варианта с IN.
- В случае с IN при проверке условия будет поиск по хеш таблице.
Q: Работе с динамической таблице получаю ошибку 'Value is too long'
A: Есть довольно жесткие лимиты на размер значений в динамических таблицах. Размер одного значения (ячейки таблицы) не должен превосходить 16 МБ, а длина всей строки - 128 МБ и 512 МБ с учётом всех версий. Всего в строке может быть не более 1024 значений с учётом всех версий. Также есть ограничения на количество строк в запросах, которое по умолчанию равно 100000 строк в транзакции при вставке, миллион строк при select и 5 миллионов при lookup. Обратим внимание, что приближение к пороговым значениям может вызвать нестабильную работу. Если вы выходите за ограничение, нужно пересмотреть хранение данных в динамической таблице, не хранить такие длинные строки.
Q: Как очистить реплицированную таблицу с помощью CLI?
A: Реплицированную таблицу нельзя очистить атомарно, но вы можете очистить отдельные реплики с помощью операции Erase. Для этого понадобится включить так называемый «bulk insert» для всего кластера, выставив:
//sys/@config/tablet_manager/enable_bulk_insert
в%true
//sys/controller_agents/config/enable_bulk_insert_for_everyone
в%true
(обратите внимание на отсутствие@
)
Если последний указанный узел не существует, создайте его с помощью команды:
$ yt create document //sys/controller_agents/config --attributes '{value={}}'
Q: При чтении из динамической таблицы получаю ошибку 'Timed out waiting on blocked row'
A: Ошибка возникает при конфликтах чтения-записи: вы пытаетесь читать по ключу, который затрагивается конкурирующей транзакцией. Система должна дождаться результата транзакции, чтобы гарантировать требуемый уровень изоляции между транзакциями.
Если вам не требуется строгая консистентность, вы можете ослабить уровень изоляции читающей транзакции.
Q: При записи в динтаблицу получаю ошибку 'Row lock conflict due to concurrent ... write'
A: Ошибка возникает при конфликтах записи: вы пытаетесь записать строку, которую заблокировала конкурирующая транзакция (это может быть как запись, так и явное взятие лока в транзакции). В некоторых случаях система может дать подсказку о том, что это за транзакция (например, при конфликтах записи-записи в атрибутах ошибки будет указан идентификатор транзакции).
В общем случае для того чтобы избавиться от конфликтов, вам нужно пересмотреть то, как устроена запись в динтаблицу с вашей стороны, чтобы избежать записи в один и тот же ключ из разных мест.
В некоторых сценариях может помочь ослабление гарантий: использование режимов atomicity=none
или shared write lock. Перед тем как пользоваться ослабленными гарантиями, обязательно изучите документацию и убедитесь, что побочные эффекты для вас не страшны.