Summary: | Не очищается / удаляется lock файл /var/lib/mysql/mysql.sock.lock | ||||||
---|---|---|---|---|---|---|---|
Product: | Sisyphus | Reporter: | Горев Андрей <nekapitan2009> | ||||
Component: | MySQL-server | Assignee: | Николай Костригин <nickel> | ||||
Status: | REOPENED --- | QA Contact: | qa-sisyphus | ||||
Severity: | major | ||||||
Priority: | P5 | CC: | alimektor, doroshenkogv, iluha.companets, lav, mike, nickel, rider, shaba | ||||
Version: | unstable | ||||||
Hardware: | x86_64 | ||||||
OS: | Linux | ||||||
Attachments: |
|
Description
Горев Андрей
2022-08-30 07:27:00 MSK
(Ответ для Горев Андрей на комментарий #0) > Проблема в том,что он почему-то не всегда удаляется при остановке сервера. В > большом количестве случаев этого не происходит. Вероятность где-то от 10 до > 20%%. В файлах запуска/остановки сервера чистки нет для этого файла. > Перезапуск путём systemctl/service не помогает так как не удаляется файл. В Sisyphus и p10 проявляется? Каким образом нужно останавливать сервер, чтобы воспроизвести проблему? > Благо что я бывший системный программист UNIX - ошибку нашёл быстро, но > подумал о других только сегодня. Если исправили, можете предложить патч. (Ответ для Горев Андрей на комментарий #0) > Проблема в том,что он почему-то не всегда удаляется при остановке сервера. В > большом количестве случаев этого не происходит. Вероятность где-то от 10 до > 20%%. В файлах запуска/остановки сервера чистки нет для этого файла. > Перезапуск путём systemctl/service не помогает так как не удаляется файл. > Благо что я бывший системный программист UNIX - ошибку нашёл быстро, но > подумал о других только сегодня. > Исправьте! Т.к. ответа не последовало в течении 4 месяцев, перевожу в Worksforme. баг стабильно повторялся на платформе p10, и сейчас на p11 > он почему-то не всегда удаляется при остановке сервера поправка - он _всегда_ не удаляется при остановке сервиса, такого быть не должно (сравнивал поведение с debian), но это полбеды - файл может "залипнуть" при отключении питания, например > Вероятность где-то от 10 до 20% это вероятность совпадения PID, который записан в lock-файле с уже существующим в системе (любого процесса) с вероятностью 100% повторить баг можно так: 1) остановить сервис (lock-файл остаётся) 2) изменить lock-файл, записав в него PID любого существующего процесса в системе 3) запустить сервис - будет ошибка для решения проблемы предлагаю "костыль" (другого способа не вижу), благо у сервисного файла `/lib/systemd/system/mysqld.service` уже есть ``` ExecStartPre=/etc/chroot.d/mysql.all ``` где в свою очередь вызывается `mysql.lib`, который и предлагаю добавить строками ``` # socket lock file issue #43651 if [ -f ./mysql.sock.lock ] && [ "$(pidof mysqld)" != "$(cat ./mysql.sock.lock)" ]; then rm ./mysql.sock.lock fi ``` я пробовал запускать без `chroot` - результат тот же пробовал искусственно повторить ситуацию на debian (в т.ч. на Астре) - не получилось, ошибки не происходит кстати, вероятность ошибки повышается при рестарте системы, в случае сервис не перезапускался после предыдущего рестарта - в таком случае PID'ы будут небольшие, в одном "кучном" диапазоне я пробовал запускать без `chroot` - результат тот же пробовал искусственно повторить ситуацию на debian (в т.ч. на Астре) - не получилось, ошибки не происходит кстати, вероятность ошибки повышается при рестарте системы, если сервис не перезапускался после предыдущего рестарта - в таком случае PID'ы будут небольшие, в одном "кучном" диапазоне поотлаживал - всё работает "как задумано", вот только не понимаю, почему в debian сымитировать эту ошибку не получается, лезть ещё там в отладку уже лень ) `MySQL/sql/conn_handler/socket_connection.cc:775` ``` if (read_pid != cur_pid && read_pid != parent_pid) { if (kill(read_pid, 0) == 0) { LogErr(ERROR_LEVEL, ER_CONN_UNIX_PID_CLAIMED_SOCKET_FILE, static_cast<int>(read_pid)); return true; } } ``` > не понимаю, почему в debian сымитировать эту ошибку не получается
подозреваю, что разница в том, что там pid- и lock-файлы создаются в /var/run, а не в /var/lib
Шаги для воспроизведения ошибки: 1. Установить MySQL: # apt-get install -y MySQL-server && \ systemctl enable --now mysqld.service && \ systemctl status mysqld.service --no-pager -l && \ systemctl disable --now mysqld && \ reboot 2. Создать скрипт: # cat > run.sh <<'EOF' #!/bin/bash -xe spawn_pids() { NUM_PROCESSES=$1 current_pid="" mysql_pid="$(cat /var/lib/mysql/mysql.sock.lock)" for ((i=1; i<=NUM_PROCESSES; i++)); do sleep 600 & current_pid=$! if [[ "$mysql_pid" == "$current_pid" ]]; then echo "MySQL ($mysql_pid) created. OK!" sleep 10 return 0 fi done } systemctl status mysqld.service --no-pager -l && (echo "Looks like MySQL is running!.. stop it.") ||: spawn_pids 10000 systemctl start mysqld.service && \ sleep 5 systemctl status mysqld.service --no-pager -l EOF # chmod +x run.sh 3. Перезагрузить машину: # reboot 4. Запустить скрипт: ./run.sh Ожидаемый результат: Успешное выполнение скрипта Фактический результат: ошибка MYSQL: [ERROR] [MY-010259] [Server] Another process with pid 7419 is using unix socket file. [ERROR] [MY-010268] [Server] Unable to setup unix socket lock file. Воспроизводится в P11. > pid- и lock-файлы создаются в /var/run
попробовал запустить в Альте MySQL без chroot, используя /run:
[mysqld]
socket = /var/run/mysqld/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid
это решило проблему автоматического удаления lock-файла при нормальном завершении сервиса
к тому же, учитывая самоочищение /run при перезагрузке - это решает и проблему с блокированием сервиса практически на 100%
(вероятность получить уже имеющийся в системе PID при рестарте сервиса - ооочень мала)
Created attachment 17809 [details] патч так более правильно: ``` # socket lock file issue (ALT#43651) if [ -f ./mysql.sock.lock ]; then lock_pid=$(cat ./mysql.sock.lock) if [ "mysqld" != "$(cat /proc/$lock_pid/comm)" ]; then rm ./mysql.sock.lock fi fi ``` (Ответ для Evgeny Shesteperov на комментарий #9) > Шаги для воспроизведения ошибки: > ... А что делает функция spawn_pids ? |