Длительный запрос innodb генерирует большой файл отмены в mariadb - PullRequest
0 голосов
/ 29 февраля 2020

У меня большой запрос в php, использующий MYSQLI_USE_RESULT, чтобы не помещать все результаты в память php. Потому что, если я использую MYSQLI_STORE_RESULT, он поместит все данные в память для всех результатов, что занимает несколько ГБ ОЗУ, вместо того, чтобы получать строку за строкой. Он возвращает миллионы строк, и каждая строка будет генерировать запрос API, поэтому запрос будет выполняться в течение нескольких дней. В то же время у меня есть другие mysql запросы, которые обновляют / вставляют таблицы, связанные с первым запросом, и я думаю, что это вызывает рост журнала отмены без остановки.

Я настраиваю innodb_undo_tablespaces = 2 и innodb_undo_log_truncate = ВКЛ, поэтому журнал отмены отделен от ibdata1, но файлы отмены по-прежнему велики, пока я не уничтожу запросы, которые выполнялись в течение нескольких дней.

Я выполнил «УСТАНОВИТЬ УРОВЕНЬ ИЗОЛЯЦИИ СДЕЛКИ СДЕЛКИ ЧИТАТЬ НЕОБЕСПЕЧЕННЫЙ;» перед запуском длинного запроса, надеясь, что это предотвратит рост файла отмены, но этого не произошло.

Другие запросы, которые обновляются / вставляются, имеют автокоммит.

В 1-2 день, файл отмены уже 40 ГБ.

Вопрос: как предотвратить увеличение этого файла отмены? Поскольку я не хочу сохранять предыдущую версию данных, пока выполняется запрос. Это не важно, если я получу обновленные данные вместо данных, которые были на момент запроса.

1 Ответ

1 голос
/ 01 марта 2020

Независимо от уровня изоляции транзакции, данный запрос всегда устанавливает sh фиксированный моментальный снимок, который требует сохранения данных в том состоянии, в котором они были при запуске запроса.

Другими словами, READ-COMMITTED или READ-UNCOMMITTED позволяют последующим запросам в той же транзакции видеть обновленные данные, но один запрос никогда не увидит изменяющийся набор данных. Таким образом, одновременное обновление данных приведет к тому, что старые версии записей будут скопированы в журнал отмены, и эти версии записей будут сохраняться там до тех пор, пока ваш долгосрочный запрос не будет завершен.

READ-UNCOMMITTED больше не помогает чем ЧИТАЕТЕ. На самом деле, мне никогда не приходилось использовать READ-UNCOMMITTED по любой причине. Разрешение «грязного чтения» незавершенных транзакций нарушает правила баз данных ACID и приводит к аномалиям.

Единственный способ избежать длительного роста вашего журнала отмены - завершить sh ваш запрос.

Самый простой способ добиться этого - использовать несколько краткосрочных запросов, каждый из которых извлекает подмножество результата. Завершите sh каждый запрос своевременно.

Другим решением было бы запустить весь запрос для миллионов строк результата и сохранить результат где-то , который не ограничен изоляцией транзакции InnoDB.

  • Таблица MyISAM
  • Очередь сообщений
  • Простой файл на диске
  • Кэш, такой как Memcached или Redis
  • PHP память (но вы сказали, что нет это неудобно из-за размера)
...