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 产生了同样的错误。

4

1 回答 1

1

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

这也是我在下面的查询中使用unnestand的子查询构造的原因ARRAY

请考虑这个替代查询。它产生相同的信息,只是没有重复的行并且速度提高了 100 倍。另外,我敢保证,没有僵局。

当然,此查询仅适用于 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

我使用特殊的铸造操作table_oid::regclass。这会产生您当前活动的表名search_path。这可能是也可能不是你想要的。要使此查询包含每个表名的绝对路径(模式),您可以设置search_path如下

SET search_path = pg_catalog;
SELECT ...

你可能知道其余的,但我把它包括给公众。
如果您继续此会话并希望恢复默认的 search_path,则:

RESET search_path;

如果您应该使用 custom search_path,则必须重新设置它。

于 2011-10-25T06:11:25.713 回答