【发布时间】: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 本身创建的。