Невозможно изменить строку в PostgreSQL - PullRequest
0 голосов
/ 11 октября 2011

В настоящее время я пытаюсь вести базу данных postgres с информацией об игроках, когда у меня возникла проблема с одним из наших игроков.Игрок пришел к нам и сказал, что не может загрузить своего персонажа в игровой мир.Я сделал небольшое предложение SELECT, чтобы получить информацию об игроке без проблем.Однако, когда они пытаются использовать персонажа, мы обновляем поле в строке, в котором говорится, что персонаж игрока активен.Однако мы заметили, что мы не можем запустить обновление или оператор удаления в этой строке.Каждая вторая строка в таблице изменяется без каких-либо проблем.

Один из наших администраторов БД думал, что это была блокировка, которая была применена к этой строке, но после дальнейшего изучения не увидел ничего, что могло бы блокировать эту строку.

Любые советы или предложения приветствуются.

Ответы [ 2 ]

0 голосов
/ 12 октября 2011

Если ваша таблица player большая и столбец status обновляется очень много (как вы и предполагали), в то время как другие столбцы обновляются не очень часто, тогда было бы неплохо иметьдополнительная таблица player_status.

То же самое верно , если , у вас есть много сложных триггеров, которые срабатывают от UPDATE до player (которые могут вызвать проблему под рукой).

Из-за MVCC PostgreSQL каждый UPDATE фактически эквивалентен "INSERT new, DELETE old".Старый ряд позже будет пылесосить.Это вызывает некоторое раздувание таблицы и индекса и запись на диск.Если это происходит только для сравнительно крошечной таблицы, такой как

CREATE TABLE (
  player_id integer references player (player_id)
, status bool -- or integer for more possible states?
);

.., это может быть немного быстрее со всех сторон.Это может или не может облегчить проблему, которую вы видите.


Для диагностики непосредственной проблемы: pgAdmin имеет инструмент «Состояние сервера», с помощью которого вы можете легко проверить статусвсех соединений.Выберите базу данных и используйте Tools -> Server Status.

0 голосов
/ 12 октября 2011

Это, безусловно, звучит как замок.

Подход "большой молоток" заключается в том, чтобы отразить (остановить / запустить) вашу базу данных, чтобы уничтожить все выполняющиеся запросы.

Подход "скальпеля" заключается в запуске show full processlist; и попытке найти выполняющийся запрос, который мог бы создать блокировку. Обратите внимание, что сам запрос может не блокировать строку, но более ранний запрос в той же транзакции мог заблокировать ее. Любой длительный запрос является подозрительным.

EDIT

Я обнаружил проблему в 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 '%'"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...