MySQL использует невероятное количество памяти для импорта 1-2 ГБ файлов SQL

У меня есть сервер MySQL, работающий на машине Ubuntu 18.04 через Docker. В машине 32 ГБ ОЗУ.

У меня около 300 файлов SQL по 1-2 ГБ, которые нужно импортировать в базу данных на сервере, в одну таблицу.

Сама база данных полностью пуста, и есть только один таблицу.

Когда я пытаюсь импортировать некоторые файлы, я вижу всплеск использования памяти до 32 ГБ (100%), а после выделения 100 ГБ памяти подкачки максимальное значение, которое я видел, достигло 60 ГБ (60 ГБ + 32 ГБ = 92 ГБ !!!)

Принимая во внимание, что MySQL пытается использовать 92 ГБ ОЗУ для импорта файла SQL размером 1 ГБ в одну таблицу в пустой базе данных, что он мог делать? Это не похоже на утечку памяти, потому что после завершения импорта файла память становится нераспределенной.

Я, вероятно, должен упомянуть, что MySQL использует том Docker, к которому хост имеет прямой доступ к файлам для хранения своих данных.

Я пробовал много разных конфигураций, чтобы решить эту проблему, и, кроме того, иногда получаю ошибку Сервер MySQL ушел .

Я пробовал следующее:

  • Изменение таблицы из InnoDB в MyISAM и работает ALTER TABLE tbl_name DISABLE KEYS
  • Настройка autocommit = 0 , unique_checks = 0 , foreign_key_checks = 0
  • Настройка ] max_allowed_packet = 999999999G и соответствующие переменные тайм-аута для аналогичных значений
  • Использование mysqltuner.pl для генерации некоторых оптимальных параметров конфигурации InnoDB (показано ниже)

Сами файлы SQL - это буквально один Оператор INSERT с тысячами строк.

Что я могу сделать? Я подумал о том, чтобы разделить инструкцию INSERT на несколько разных INSERT, но это потребует некоторого обширного рефакторинга кода из-за многопроцессорной обработки моей программы, которая генерирует файлы SQL.

my.cnf :

[mysqld]
max_allowed_packet = 9999999G
wait_timeout = 99999999999
key_buffer_size=10M
innodb_buffer_pool_size=21G
innodb_log_file_size=2G
innodb_buffer_pool_instances=21
innodb_file_per_table
net_read_timeout=999999999999
net_write_timeout=999999999999

pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# Custom config should go here
!includedir /etc/mysql/conf.d/

Проблема постоянно сохранялись даже после добавления переменных innodb _ * .

показать глобальные переменные :

https://pastebin.com/raw/pXK4MgFb

Большое спасибо

2
задан 9 September 2019 в 19:10
2 ответа

По своему опыту могу сказать:

  • во время набора импорта:
    • max_allowed_packet = 10G (чтобы сделать память доступной для INSERT )
    • innodb_buffer_pool_size = 10G (или меньше) для освобождения памяти сервера, вы можете увеличить это позже, когда будете использовать сервер для запросов,но для вставок это почти бесполезно
    • innodb_flush_log_at_trx_commit = 0 для повышения производительности ввода-вывода (обязательно удалите или установите 1 или 2 для производственного использования!)

Кроме того, существует проблема с INSERT , слишком большие для одной транзакции. Обычно, если ваша транзакция слишком велика для журнала повторов, она завершится ошибкой. Определенно установите AUTOCOMMIT = 1 , удалите все строки START TRANSACTION из файлов дампа и, если это не помогает, увеличьте размер файла журнала: https: // dba. stackexchange.com/a/1265/12685


Вдобавок я понял, что вы создаете эти файлы SQL программно. Будет более эффективно запускать эти вставки одну за другой на сервер базы данных, особенно с настройками выше, и это будет быстро, если вы используете INSERT DELAYED .

0
ответ дан 3 December 2019 в 12:29

Ни один объем оперативной памяти или дискового пространства в цивилизованном мире не может вместить то, что max_allowed_packet = 9999999G хочет выделить! Положите это по умолчанию, или максимум 256M.

Сами SQL-файлы - это буквально один INSERT-оператор с тысячами строк.

Это оптимально.

Значит, общий размер таблицы где-то равен половине терабайта? Время, затрачиваемое на запись такого количества диска, зависит от типа диска.

Не не используют пространство подкачки; это только замедляет MySQL. Много. Однако, ваши настройки, кажется, на самом деле не используют пространство подкачки. 21Гб для buffer_pool должен удерживать использование оперативной памяти значительно ниже 32Гб физического размера. Однако, вы говорите, что он вырос до 100%? Наверное, я что-то упускаю. Если есть какая-то подкачка, MySQL замедлится, поэтому немного уменьшите размер buffer_pool_size, чтобы избежать подкачки.

autocommit=0 с InnoDB не эффективен -- Если нет COMMIT, то данные вставляются, а затем откатываются обратно. Если есть COMMIT, то он должен проделать большую работу, чтобы подготовиться к откату. Установите на ON.

Отключение и повторное включение "клавиш" 300 раз? Это означает, что индексы перестраиваются 300 раз. Работали ли файлы медленнее и медленнее, когда вы проходили через 300?

.
1
ответ дан 3 December 2019 в 12:29

Теги

Похожие вопросы