Почему MySQL говорит, что мне не хватает памяти?

9

Я пытался выполнить довольно большой INSERT...SELECTв MySQL с JDBC, и я получил следующее исключение:

Exception in thread "main" java.sql.SQLException: Out of memory (Needed 1073741824 bytes)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)

Поскольку я на самом деле не возвращаю объект ResultSet, я подумал, что пространство кучи Java не должно быть проблемой. Тем не менее, я все равно пытался поднять его, и это не помогло. Затем я попытался выполнить инструкцию в MySQL Workbench, и я получил по существу то же самое:

Error Code 5: Out of memory (Needed 1073741816 bytes)

У меня должно быть достаточно оперативной памяти для выполнения этих операций (достаточно, чтобы вместить всю таблицу, из которой я выбираю), но я предполагаю, что существуют различные настройки, которые необходимо настроить, чтобы использовать всю свою память. Я использую большой дополнительный экземпляр Amazon EC2 с двойной памятью и Windows Server 2008 AMI. Я попытался поиграться с файлом my.ini, чтобы использовать лучшие настройки, но, насколько я знаю, я мог бы ухудшить ситуацию. Вот дамп этого файла:

[client]
port=3306
[mysql]
default-character-set=latin1
[mysqld]
port=3306
basedir="C:/Program Files/MySQL/MySQL Server 5.5/"
datadir="C:/ProgramData/MySQL/MySQL Server 5.5/Data/"
character-set-server=latin1
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
max_connections=100
query_cache_size=1024M
table_cache=256
tmp_table_size=25G
thread_cache_size=8
myisam_max_sort_file_size=100G
myisam_repair_threads = 2
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_additional_mem_pool_size=26M
innodb_flush_log_at_trx_commit=2
innodb_log_buffer_size=13M
innodb_buffer_pool_size=23G
innodb_log_file_size=622M
innodb_thread_concurrency=18
innodb_file_per_table=TRUE
join_buffer_size=4G
max_heap_table_size = 10G

Так что это просто вопрос изменения вышеуказанных настроек, чтобы они лучше работали в моей среде? Если да, какие настройки я должен использовать? Я единственный, кто когда-либо использовал этот экземпляр; Я использую его для своего личного хобби проекта, который включает в себя статистический анализ больших наборов данных. Таким образом, я могу позволить ему использовать все доступные ресурсы для моих собственных запросов.

Если проблема не в изменении этих настроек, в чем проблема? Спасибо за любую помощь, которую вы можете предложить, как лучше настроить все.

Майкл МакГоуэн
источник
Любой, кто использует кеш запросов 1g, понятия не имеет, что он делает.
@winmutt Вы вполне можете быть правы, но ваш комментарий никому не поможет без дальнейших объяснений. Не могли бы вы помочь нам, объяснив свои чувства?
Майкл Макгоуэн
Удобный инструмент для начала работы - tools.percona.com/wizard
KCD

Ответы:

9

Учитывая, что это установка Windows, @DTest все еще указывал правильное начальное направление.

Примените следующую формулу:

Большинство людей используют это:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + (read_buffer_size + sort_buffer_size) X max_connections

Я предпочитаю это:

Maximum MySQL Memory Usage = innodb_buffer_pool_size + key_buffer_size + ((read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size) X max_connections)

Эти переменные необходимо корректировать до тех пор, пока формула не даст 80% установленной оперативной памяти или меньше.

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
RolandoMySQLDBA
источник
4

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

query_cache_size=1024M
myisam_max_sort_file_size=100G
myisam_sort_buffer_size=10G
key_buffer_size=5000M
bulk_insert_buffer_size = 4000M
read_buffer_size=8000M
read_rnd_buffer_size=8000M
sort_buffer_size=1G
innodb_buffer_pool_size=23G

Некоторые размеры буфера выделяются для каждого потока, например, myisam_sort_buffer_size 10G выделяет 10G для каждого потока.

Сначала я резко уменьшу эти значения, а затем выясню, какие значения вам действительно нужны для выделения такого большого объема ОЗУ (если оно есть).

Дерек Дауни
источник
4

Быстрый способ определить, сколько памяти MySQL считает, что может выделить:

wget mysqltuner.pl

perl mysqltuner.pl

Когда вы запустите этот скрипт, он скажет вам, какой процент установленной оперативной памяти MySQL считает безопасным для себя. Если ответ превышает 100%, вам определенно необходимо уменьшить размер буфера. Основными из них являются:

sort_buffer_size
read_buffer_size
read_rnd_buffer_size
join_buffer_size
max_connections
key_buffer_size ( на самом деле не эффективны в прошлом 4G)

@DTest уже установил для вас направление в своем ответе, поэтому +1 для его ответчика. Сценарий Perl сообщит вам, что произойдет, если вы не установите его или измените какое-либо значение. Вот пример:

Мой клиент имеет
read_buffer_size = 128K
read_rnd_buffer_size = 256K
sort_buffer_size = 2M
join_buffer_size = 128K
max_connections = 1050

Вот вывод из mysqltuner.pl:

MySQLTuner 1.2.0 - Отчеты об основных
ошибках Hayden , запросы функций и загрузки по адресу http://mysqltuner.com/
Запустите с «--help» для дополнительных опций и фильтрации выходных данных.
Пожалуйста, введите свой административный логин MySQL: lwdba
Пожалуйста, введите свой административный MySQL пароль:

-------- Общая статистика ---------------------------------------- ----------
[-] Проверка пропущенной версии для сценария MySQLTuner
[OK] В настоящее время работает поддерживаемая версия MySQL 5.0.51a-community-log
[!!] Переключиться на 64-разрядную ОС - MySQL в настоящее время не может использовать вся ваша оперативная память

-------- Статистика механизма хранения --------------------------------------- ----
[-] Статус: + Архив -BDB + Federated + InnoDB -ISAM -NDBCluster
[-] Данные в таблицах MyISAM: 319M (Таблицы: 108)
[-] Данные в таблицах InnoDB: 2M (Таблицы: 5)
[!!] Всего фрагментированных таблиц: 22

-------- Показатели эффективности ---------------------------------------- ---------
[-] Up для: 52d 23h 15m 57s (72M q [15,875 qps], 241K conn, TX: 2B, RX: 1B)
[-] Чтение / запись: 59% / 41%
[-] Всего буферов: 34,0M глобальных + 2,7M на поток (максимум 1050 потоков)
[!!] Выделение> 2 ГБ ОЗУ в 32-разрядных системах может вызвать нестабильность системы
[!!] Максимально возможное использование памяти: 2,8 ГБ (72% установленной оперативной памяти)
[OK] Медленные запросы: 0% (54 / 72M)
[OK] Максимальное использование доступных подключений: 6% (65/1050)
[OK] Размер буфера ключа / всего индексов MyISAM: 8,0M / 82.1M
[OK] Частота обращений к буферу ключей: 100.0% (4B кэшировано / 1M операций чтения)
[!!] Кэш запросов отключен
[OK] Сортировки, требующие временных таблиц: 0% (0 временных сортировок / 948K сортировок)
[OK] Временные таблицы, созданные на диске: 3% (11K на диске / 380K всего)
[!!] Кэш потоков отключен
[!!] Частота обращений в кэш таблиц: 0% (64 открытых / 32K открытых)
[OK] Открыть файл используемый предел: 2% (125 / 5K)
[OK] Блокировки таблицы получены немедленно: 99% (немедленные 30M / 30M блокировки)
[OK] Размер данных InnoDB / пул буферов: 2,7M / 8,0M

-------- Рекомендации ----------------------------------------- ------------
Общие рекомендации:
Запустите OPTIMIZE TABLE для дефрагментации таблиц для повышения производительности.
Включите медленный журнал запросов для устранения проблем с ошибочными запросами.
Установите thread_cache_size в качестве начального значения
4, постепенно увеличивая table_cache, чтобы избежать ограничений дескриптора файла.
Переменные настроить:
query_cache_size (> = 8M)
thread_cache_size (начиная с 4)
table_cache (> 64)

Пожалуйста, обратите внимание на показатели производительности

[-] Общее количество буферов: 34.0M глобально + 2.7M на поток (максимум 1050 потоков)

что MySQL может выделить до 72% установленной оперативной памяти в зависимости от настроек в /etc/my.cnf.

34M основан на сочетании innodb_buffer_pool_size и key_buffer_size

2.7M на поток основывалось на read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size.

Кратные 2.7M основаны на max_connections.

Поэтому вы должны настроить эти параметры до тех пор, пока в отчете метрик производительности не будет указано, что у вас установлено менее 100% (предпочтительно менее 80%) установленной оперативной памяти.

RolandoMySQLDBA
источник
Я не уверен, что смогу использовать твой инструмент; Я использую Windows. В документации упоминается, что Windows не поддерживается, но я все равно попробовал. Когда я попытался запустить его, он указал, что не может найти mysqladmin в моем $ PATH, но каталог bin в MySQL действительно находится в моем $ PATH.
Майкл МакГоуэн
Извините, я не заметил данные Windows. Я добавлю другой ответ.
RolandoMySQLDBA
1

Вы не сказали, сколько у вас оперативной памяти? Я предполагаю, что это по крайней мере 32 ГБ.

innodb_buffer_pool_size - 23G

Хорошо для этого много оперативной памяти.

query_cache_size = 1G

Слишком большой. Это неэффективно, когда оно большое. Рекомендую не более 50М.

key-buffer_size = 5G

Там может быть жесткий предел 4G (все еще) в Windows, имеет жесткий предел 4G. Ваш 5G, возможно, превратился в 1G. Во всяком случае, если все ваши столы InnoDB, зачем тратить баран. Установите его на 50M.

Поскольку сообщение об ошибке было ровно 1G, оно пахнет как sort_buffer_size. 32M может быть разумным.

Рик Джеймс
источник