【问题标题】:Why would ALTER TABLE DROP CONSTRAINT on an empty table take a long time?为什么空表上的 ALTER TABLE DROP CONSTRAINT 需要很长时间?
【发布时间】:2013-07-11 23:58:52
【问题描述】:

我试图在单个事务中将几百万行数据加载到一个表中(一个“跟随”表,其中包含用户表的两个外键以及这些键上的关联索引)。由于系统内存耗尽,我最初的尝试导致我的脚本崩溃。

一些研究得出的结论是崩溃是因为外键约束,所以我验证了表是空的(即导致进程被杀死的事务没有完成)并将我的脚本修改为删除外键约束和索引以插入数据。我的意图是之后重新创建约束和索引。

但是,尽管表完全为空,但用于删除表上的第一个外键约束的 ALTER TABLE DROP CONSTRAINT 命令需要很长时间(数十分钟)。

我唯一能想到的是,和我写到表中的大量数据然后没有提交有关,因为脚本崩溃了。但是当然,由于事务没有提交,我在数据库中找不到该数据的任何痕迹。

什么可能导致此查询变慢(或可能根本不运行;在撰写本文时它仍在进行中),我该如何避免?

数据库中还有其他打开的事务(几个小时长的事务正在迁移其他非常大的表),但这些事务都没有触及后续表。

编辑:pg 锁如下:

db=#  select relation::regclass, * from pg_locks where not granted;
-[ RECORD 1 ]------+--------------------
relation           | auth_user
locktype           | relation
database           | 53664
relation           | 54195
page               | 
tuple              | 
virtualxid         | 
transactionid      | 
classid            | 
objid              | 
objsubid           | 
virtualtransaction | 5/343
pid                | 17300
mode               | AccessExclusiveLock
granted            | f

上面的 pid (17300) 只是 ALTER TABLE 查询本身。没有其他锁,也没有等待锁的进程。

【问题讨论】:

  • 检查pg_locks验证没有其他事务在表上锁定。即使是读锁也会阻止ALTER TABLE
  • @CraigRinger 编辑添加锁表信息:长和短是唯一的锁是由 ALTER TABLE 本身创建的。

标签: postgresql postgresql-9.1


【解决方案1】:

检查 pg_locks 并确认没有其他事务在该表上拥有锁。即使是读锁也会阻止ALTER TABLE

\x

select 
  pg_class.relname,
  pg_locks.*
from pg_locks 
left outer join pg_class ON (pg_locks.relation = pg_class.oid)
where pg_locks.relation = 'auth_user'::regclass;

通过在原始查询中过滤 where not granted,您只会显示未完成的锁,而不是阻止它们的锁。

这个锁未被授予的事实告诉我这是一个锁定问题。另一个事务持有此表的锁,阻止ALTER TABLE 获取它需要继续进行的AccessExclusiveLock。这可能只是 SELECTed 在某个时候从表中处理的事务。

您可以通过加入pg_stat_activity找到它:

select 
  c.relname,
  l.*,
  psa.*
from pg_locks l
inner join pg_stat_activity psa ON (psa.pid = l.pid)
left outer join pg_class c ON (l.relation = c.oid)
where l.relation = 'test'::regclass;

这将向您显示该表中持有或等待锁的事务、锁是什么、这些事务当前正在运行什么语句等。

(对于旧版本:pg_stat_activity.pid 曾经是procpid。因此,如果您使用的是旧 PostgreSQL,请适当更改查询。或更新。)

【讨论】:

  • 事实证明,由于某种原因,一个单独的进程正在锁定用户表(跟随表具有外键关系)正在阻止 ALTER TABLE 查询。我不明白为什么锁定用户表会阻止它,但谜团已经解决。谢谢!
  • @JohnBarça 试图编辑:“在 9.2 之前的 Postgres 版本中,pg_stat_activity pid 被称为 procpid”。
猜你喜欢
  • 2011-11-27
  • 2018-04-24
  • 1970-01-01
  • 2021-02-27
  • 2012-01-14
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多