我写了一个迁移脚本,它在sqlite上运行得很好,但是如果我尝试将其应用到Postgres,它将永远无法运行。
通过一个简单的ps,我可以看到postres卡在“创建表等待”上。
有什么最佳实践吗?

最佳答案

如果它真的卡在锁上,你需要看看它在等什么。CREATE TABLE卡在锁上是很奇怪的,但这并非不可能。
获取卡住的进程ID
获取等待后端的进程ID。您可以在ps中找到它,或者通过SELECT中的pg_stat_activitying来查找具有waitingtrue的进程,以查找您感兴趣的命令:

SELECT * FROM pg_stat_activity WHERE waiting;

弄清楚它在等什么锁
通过查询,查看卡住的PID正在等待的锁:
SELECT * FROM pg_locks WHERE pid = <the-waiting-pid> AND NOT granted;

您可以将这两个步骤结合起来:
\x

SELECT *
FROM pg_locks l
INNER JOIN pg_stat_activity s ON (l.pid = s.pid)
WHERE waiting
AND NOT granted;

然后查看结果,或者在pg_locks字段上使用LIKE过滤器来查找您试图确定锁定问题的查询。
找到锁的人
现在,您可以查询s.query来确定哪个进程找到了该锁,以及它们在做什么。
假设我们发现,pg_locks正在等待一个锁类型=create锁模式=relation在relation=AccessExclusiveLock被授予。我们希望找到其他会话在该关系上持有的锁:
SELECT *
FROM pg_locks l
INNER JOIN pg_stat_activity s ON (l.pid = s.pid)
WHERE locktype = 'relation'
AND   relation = 14421;

这应该可以告诉您是什么阻碍了创建。
皱纹
这里有a handy lock monitoring query on the PostgreSQL wiki,但它只能找到行级锁。所以它对DDL通常没有帮助。
另外,我故意不将整个数据组合成一个查询。在accessExclusiveLock的情况下,找到通过pid阻塞给定后端的锁持有者就足够简单了,但是对于较弱的锁请求,这就不那么简单了——我必须写出在SQL中哪些锁与哪些锁冲突的规则,这就相当复杂了。最好只是盯着看。

10-07 13:09
查看更多