| 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 ? прошёл месяц... в чём сложность решить вопрос? ? (Ответ для Vitaly Lipatov на комментарий #12) > А что делает функция spawn_pids ? Заполняет таблицу PID процессом (sleep 600). Подразумевается, что проверка выполняется сразу же после старта системы. Так как в файле /var/lib/mysql/mysql.sock.lock хранится старый PID (который становится занят, благодаря скрипту), то сервис пытается использовать его и выдаётся ошибка: Another process with pid 7419 is using unix socket file. ? ? |