Как увеличить максимальное число открытых файлов для MySQL

Материал из Wiki МИАЦ ВО
Перейти к навигации Перейти к поиску

Взято тут.

Проблема

Зачастую при увеличении параметров max_connections или table_open_cache в более высокие значения они не могут быть установлены из-за ограничение ОС. При старте MySQL в логе error.log мы видим предупреждения:

2018-04-27T01:01:18.027751Z 0 [Warning] Changed limits: max_open_files: 1024 (requested 32310)
2018-04-27T01:01:18.027846Z 0 [Warning] Changed limits: max_connections: 214 (requested 300)
2018-04-27T01:01:18.027853Z 0 [Warning] Changed limits: table_open_cache: 400 (requested 16000)

Которые говорят, что наши параметры не могут быть установлены.
Но как это исправить?
Читаем ниже.

Исходные данные

ОС: Ubuntu 16.04.4 LTS
БД: Oracle MySQL 5.7.22
Задача: Решить проблему с невозможностью установки параметров max_connections=300 и table_open_cache=16000

При старте MySQL в логе error.log мы можем увидеть предупреждения вида:

2018-04-27T01:01:18.027751Z 0 [Warning] Changed limits: max_open_files: 1024 (requested 32310)
2018-04-27T01:01:18.027846Z 0 [Warning] Changed limits: max_connections: 214 (requested 300)
2018-04-27T01:01:18.027853Z 0 [Warning] Changed limits: table_open_cache: 400 (requested 16000)

При этом в файле конфигурации /etc/mysql/mysql.conf.d/mysqld.cnf у нас установлено:

max_connections        = 300
table_open_cache       = 16000

Но MySQL не может установить эти значение и они понижаются до разрешенных, а именно max_connections всего до 214 разрешенных соединений, а table_open_cache до 400.

Если посмотреть настройки MySQL, то можем увидеть такую картину:

# mysql -u root -p

mysql> show global variables like '%max_connections%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 300   |
+-----------------+-------+
1 row in set (0,00 sec)
 
mysql> show global variables like '%open_files_limit%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| open_files_limit | 1024  |
+------------------+-------+
1 row in set (0,00 sec)
 
mysql> show global variables like '%table_open_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| table_open_cache | 400   |
+------------------+-------+
1 row in set (0,00 sec)

Вроде как max_connections и установлен 300, но остальные настройки явно не те, что нам нужны.
Корень проблемы кроется в ограничении ОС на количество открываемых файловых дескрипторов для процесса mysqld, посмотреть ограничение мы можем так:

# cat /proc/$(pgrep mysqld)/limits | grep open
Max open files            1024                 4096                 files

В ней мы видим, что максимально разрешено открывать не более 1024 файловых дескрипторов.
Именно из-за этого при старте mysqld не может установить запрошенные нами опции max_connections, table_open_cache.

Решение

Давайте увеличим лимит файловых дескрипторов для mysqld на 10000.
Для начала нужно выяснить систему инициализации в нашем Linux дистрибутиве, выполняем:

strings /sbin/init | awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'

Команда выдала SYSTEMD.
Для systemd лимиты устанавливаются немного по другому, чем принято думать, а именно:

Выясним где находится unit файл для запуска MySQL:

# systemctl status mysql
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: active (running) since Пт 2018-04-27 06:01:36 +05; 6h ago
 Main PID: 6370 (mysqld)
    Tasks: 82
   Memory: 88.2G
      CPU: 1d 19h 2min 53.203s
   CGroup: /system.slice/mysql.service
           └─6370 /usr/sbin/mysqld

Создадим файл с описанием новых лимитов:

Мы выяснили, что unit файл это /lib/systemd/system/mysql.service, теперь нам нужно создать каталог /lib/systemd/system/mysql.service.d и в нем разместить файл limit.conf со следующим содержимым:

[Service]
LimitNOFILE=10000

Выполним несколько команд для этого:

mysql_systemd_dir="/lib/systemd/system/mysql.service.d"
mkdir -p ${mysql_systemd_dir}
echo "[Service]" >${mysql_systemd_dir}/limit.conf
echo "LimitNOFILE=10000" >>${mysql_systemd_dir}/limit.conf
systemctl daemon-reload

Теперь проверим будет ли наша конфигурация подхвачена:

# systemctl status mysql

● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
  Drop-In: /lib/systemd/system/mysql.service.d
           └─limit.conf
   Active: active (running) since Пт 2018-04-27 06:01:36 +05; 6h ago
 Main PID: 6370 (mysqld)
    Tasks: 82
   Memory: 88.2G
      CPU: 1d 19h 2min 53.203s
   CGroup: /system.slice/mysql.service
           └─6370 /usr/sbin/mysqld

Отлично, теперь нам нужно перезапустить MySQL:

systemctl restart mysql

Проверим лимиты:

# cat /proc/$(pgrep mysqld)/limits
Limit                     Soft Limit           Hard Limit           Units
..
Max open files            10000                 10000               files
...

Проверим настройки MySQL:

# mysql -u root -p
 
mysql> show global variables like '%max_connections%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 300   |
+-----------------+-------+
1 row in set (0,00 sec)
 
mysql> show global variables like '%open_files_limit%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| open_files_limit | 10000 |
+------------------+-------+
1 row in set (0,00 sec)
 
mysql> show global variables like '%table_open_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| table_open_cache | 16000 |
+------------------+-------+
1 row in set (0,00 sec)

Отлично, это то, что нам нужно.