2011-10-24 118 views
2

我有一个应用程序读取现有PostgreSQL 9.1数据库的结构,将其与“应该”状态进行比较并相应地更新数据库。这在大多数情况下都可以正常工作。但是,当我读取当前数据库结构时,我有几个实例死锁。负责查询读取现有的外键:为什么这个查询会死锁?

SELECT tc.table_schema, tc.table_name, tc.constraint_name, kcu.column_name, 
     ccu.table_schema, ccu.table_name, ccu.column_name 
FROM information_schema.table_constraints AS tc 
JOIN information_schema.key_column_usage AS kcu 
    ON tc.constraint_name = kcu.constraint_name 
JOIN information_schema.constraint_column_usage AS ccu 
    ON ccu.constraint_name = tc.constraint_name 
WHERE constraint_type = 'FOREIGN KEY' 

查看服务器状态在pgAdmin的显示这是已在服务器上运行的唯一活动查询/交易。尽管如此,查询不会返回。

该错误以一种方式重现:当我找到一个产生错误的数据库时,每次都会产生错误。但并非所有数据库都会产生错误。这是一个神秘的错误,我还没有办法尝试或尝试解决这个问题。所以任何输入或想法都非常感谢! PS:我的一个同事刚刚报告他使用PostgreSQL 8.4产生了同样的错误。

+0

我的机器上的测试数据库需要约8秒的时间,大约有700个表。尝试使用EXPLAIN来查看查询是如何执行的并查看所有成本。 –

+0

@Frank,谢谢!没有想到EXPLAIN,并会在下次出现错误时尝试。但目前,这不是关于运行时间,而是显然是一个僵局。查询需要1.5secs在我的数据库...如果它返回。 – Robin

回答

1

我测试过,发现你的查询很慢也是。这个问题的根源在于information_schema中的“表”实际上是复杂的视图,以根据SQL标准提供目录。在这种特殊情况下,由于外键可以构建在多个列上,所以事情更加复杂。您的查询产生重复行对于那些我怀疑可能是不良副作用的情况。

这也是在我的查询下面的子查询 - 构造与unnestARRAY的原因。

请考虑这个替代查询。它会产生相同的信息,只是没有重复的行和100x更快的。另外,我敢保证,没有死锁。

当然,这个查询只适用于PostgreSQL,不能移植到其他RDBMS。

SELECT c.conrelid::regclass AS table_name 
     ,c.conname AS fk_name 
     ,ARRAY(SELECT a.attname 
      FROM unnest(c.conkey) x 
      JOIN pg_attribute a 
      ON  a.attrelid = c.conrelid AND a.attnum = x) AS fk_columns 
     ,c.confrelid::regclass AS ref_table 
     ,ARRAY(SELECT a.attname 
      FROM unnest(c.confkey) x 
      JOIN pg_attribute a 
      ON  a.attrelid = c.confrelid AND a.attnum = x) AS ref_columns 
FROM pg_catalog.pg_constraint c 
WHERE c.contype = 'f'; 
-- ORDER BY c.conrelid::regclass::text,2 

我使用special casting operation table_oid::regclass。这会产生与当前活动的search_path一样的表名。这可能是也可能不是你想要的。对于该查询,包括每一个表名的绝对路径(模式),你可以set the search_path like this

SET search_path = pg_catalog; 
SELECT ... 

你可能都知道了,但我把它给了公众。
如果您在本次会议继续,并希望您的默认SEARCH_PATH回来,然后:

RESET search_path; 

如果你要使用自定义search_path,你将不得不再次设定。

+0

谢谢!这比我预期的要多得多!查询确实快得多。到目前为止,我还没有能够重现我的僵局。再次感谢! – Robin