无法修改PostgreSQL中的一行

时间:2011-10-11 19:58:46

标签: sql postgresql locking

我正在尝试维护一个有关玩家信息的postgres数据库,当我遇到一个玩家的问题时。玩家来到我们这里说他无法将他的角色加载到游戏世界中。我做了一个小的SELECT语句来提取玩家信息没有问题。但是,当他们尝试使用角色时,我们会更新行中表示玩家角色处于活动状态的字段。但是我们注意到我们无法在该行上运行更新或删除语句。表中的每一行都会被修改而没有任何问题。

我们的数据库管理员认为它是在该行上应用的锁,但经过进一步调查后,看不到任何可能锁定该行的内容。

非常感谢任何建议或建议。

2 个答案:

答案 0 :(得分:0)

这当然听起来像锁。

“大锤”方法是弹跳(停止/启动)数据库以杀死任何正在运行的查询。

“手术刀”方法是运行show full processlist;并尝试查找正在运行的可能已创建锁定的查询。请注意,查询本身可能不会锁定该行,但同一事务中的早期查询可能已将其锁定。任何长时间运行的查询都是可疑的。

修改

我在postgres中发现了一个问题,即使在重启之后也会锁定。以下是您查找和修复它的方法:

运行此查询:

select * from pg_prepared_xacts

Here's the doc for this system view

如果有任何行,则表示存在孤立/悬空事务,即使在重新启动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 :(得分:0)

如果您的表player很大且列status经常更新(如您暗示的那样),而其他列不经常更新,则可能是最好有一张额外的桌子player_status

同样如此如果您在UPDATEplayer时触发了很多复杂的触发器(可能会导致问题)。

由于PostgreSQL's MVCC,每个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