2011-10-24 193 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