#sql #postgresql #locking
#sql #postgresql #блокировка
Вопрос:
В настоящее время я пытаюсь поддерживать базу данных postgres с информацией об игроках, когда столкнулся с проблемой с одним из наших игроков. Игрок пришел к нам, сказав, что он не может загрузить своего персонажа в игровой мир. Я выполнил небольшую инструкцию SELECT, чтобы без проблем получить информацию об игроке. Однако, когда они пытаются использовать персонажа, мы обновляем поле в строке, в котором говорится, что игровой персонаж активен. Однако мы заметили, что не смогли запустить инструкцию update или delete в этой строке. Каждая вторая строка в таблице изменяется без каких-либо проблем.
Один из администраторов нашей базы данных подумал, что это была блокировка, которая была применена к этой строке, но после дальнейшего расследования не увидел ничего, что могло бы блокировать эту строку.
Приветствуются любые советы или предложения.
Комментарии:
1. что-нибудь в журналах postgresql …?
2. Заглянув в журналы, когда я публиковал этот вопрос
3. » не удалось запустить обновление «: вы получаете какие-либо ошибки? Совершаете ли вы это должным образом?
4. Ошибок нет, запрос просто продолжал истекать
Ответ №1:
Это, безусловно, звучит как блокировка.
Подход «большого молотка» заключается в том, что ваша база данных загружается (останавливается / запускается), чтобы отключить все запущенные запросы.
Подход «скальпеля» заключается в запуске show full processlist;
и попытке найти выполняемый запрос, который мог создать блокировку. Обратите внимание, что сам запрос может не блокировать строку, но более ранний запрос в той же транзакции мог заблокировать ее. Любой длительный запрос является подозрительным.
Редактировать
Я обнаружил проблему в postgres, которая сохраняет блокировку даже после перезапуска. Вот как вы находите и исправляете это:
Запустите этот запрос:
select * from pg_prepared_xacts
Вот документ для этого системного представления
Если есть какие-либо строки, это означает, что есть потерянные / зависшие транзакции, которые могут удерживать блокировки даже после перезапуска postgres.
Чтобы уничтожить их, для каждой строки получите gid
(длинный UUID) и выполните это:
ROLLBACK PREPARED '<paste gid here>'
Это должно привести к исправлению ситуации.
Если вы используете платформу * nix, вы можете запустить эту единственную команду, которая сделает многое:
psql -U postgres mydatabase -c "select * from pg_prepared_xacts" | grep -v transaction | grep | | awk '{print $3}' | xargs -I % psql -U postgres mydatabase -c "ROLLBACK PREPARED '%'"
Комментарии:
1. Я попытался использовать метод ‘scalpel’, но процесс, который его использовал, был «ПРОСТАИВАЮЩИМ в транзакции». Я пытался остановить процесс, но он просто не сдвинулся с места. Мы запланировали некоторое аварийное время простоя и перезапустили весь сервер, чтобы он снова заработал. Спасибо за вашу помощь.
2. @Seb Просто подумал о чем-то еще, что может вам помочь — пожалуйста, прочитайте отредактированный ответ.