20

我编写了一个在 sqlite 上运行良好的迁移脚本,但如果我尝试将其应用于 postgres,它就会永远卡住。通过一个简单的 ps,我可以看到 postres 停留在“创建表等待”上。有什么最佳做法吗?

4

4 回答 4

34

如果它真的卡在锁上了,你需要看看它在等待什么。卡在锁上会很奇怪CREATE TABLE,但这并非不可能。

获取卡住的进程id

获取等待后端的进程ID。您可以在 中找到它ps,或者通过SELECT从中找到它pg_stat_activity,寻找具有waitingtrue 的进程,以找到您感兴趣的命令:

SELECT * FROM pg_stat_activity WHERE waiting;

弄清楚它在等待什么锁

通过查询查看卡住的 pid 正在等待的锁pg_locks

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;

然后查看结果,或LIKE在字段上使用过滤器s.query来查找您尝试识别锁定问题的查询。

找出谁持有那把锁

您现在可以查询pg_locks以找出哪个进程找到了该锁,以及它们在做什么。

假设我们发现create正在等待一个 locktype= relationlock of mode= AccessExclusiveLockon relation=14421被授予。我们希望找到其他会话对该关系持有的锁:

SELECT * 
FROM pg_locks l 
INNER JOIN pg_stat_activity s ON (l.pid = s.pid)
WHERE locktype = 'relation'
AND   relation = 14421;

这应该告诉您是什么阻止了创建。

皱纹

PostgreSQL wiki 上有一个方便的锁监控查询,但它只能找到行级锁。所以一般对DDL没有帮助。

另外,我故意不将所有内容合并到一个查询中。在 AccessExclusiveLock 的情况下,找到通过 pid 阻塞给定后端的锁持有者很简单,但是对于较弱的锁请求,这并不简单——我必须写出哪些锁与哪些锁冲突的规则在 SQL 中,这非常复杂。最好只是目不转睛。

于 2014-04-07T02:54:11.880 回答
3

您总是可以重新启动 postgresql。

于 2016-03-10T15:43:47.120 回答
2

您的数据库很可能被另一个查询锁定。

特别是如果你用他们的 GUI pgAdmin 做一些事情,我发现这种情况经常发生。(截断表特别棘手,有时 pgAdmin 崩溃并且数据库卡住了)

您要做的是重新启动完整的 postgresql 服务并重试。

确保您:

  1. 尽量减少 GUI pgadmin 的使用
  2. 如果不需要它们,请使用 psycopg2 关闭游标/数据库
于 2014-04-06T16:26:27.633 回答
1

对于遇到此问题的任何人,以下是为我解决的问题:

alembic 的标准 env.py 包含该段落

with context.begin_transaction():
    logger.info("Running Transaction.")
    context.run_migrations()

但是,如果您随后在迁移脚本中使用

config = op.get_context().config
engine = engine_from_config(config.get_section(
                            config.config_ini_section), prefix='sqlalchemy.')

事务将卡在“空闲事务”中。我不太清楚为什么,但它看起来像是事务中的事务,而外部事务从未提交。

要解决此问题,只需删除外部 begin_transaction()

# with context.begin_transaction():
logger.info("Running Transaction.")
context.run_migrations()

你应该很高兴。

于 2020-10-09T14:49:35.473 回答