Не удается изменить строку в PostgreSQL

#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 Просто подумал о чем-то еще, что может вам помочь — пожалуйста, прочитайте отредактированный ответ.