我有一个应用程序,它读取现有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 :(得分:1)
我测试过并发现您的查询非常慢。这个问题的根源是information_schema
中的“表”实际上是根据SQL标准提供目录的复杂视图。在这种特殊情况下,由于可以在多个列上构建外键,因此事情变得更加复杂。对于那些我怀疑可能会产生不良副作用的案例,您的查询会产生重复行。
这也是下面我的查询中带有unnest
和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
我使用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
,则必须重新设置。