2013-02-22 24 views
2

在生產環境中運行的穩定的,基於Web的單線程/進程perl應用程序開始間歇性地拋出此錯誤只有在系統負載很重的情況下。我們無法確定根本原因。Perl將死亡:「用法:在全局銷燬期間DBD :: Pg :: db :: DESTROY(dbh)」

Usage: DBD::Pg::db::DESTROY(dbh) during global destruction 

任何人都可以提供這種錯誤的任何解釋?當Perl在關閉之前清理時,如果不帶參數調用DESTROY(self?),它似乎是從Pg.sx拋出的。 (我看到這樣的信息在通過谷歌舊的源代碼,但不是在我們的版本。)我們的環境:

  • OS:在FreeBSD 8.3-STABLE
  • 的Perl v5.14.2
  • DBD ::第2版。 19.3
  • 的PostgreSQL:v9.2.3
+0

您的代碼是否曾經明確地調用(或者可能轉到)DESTROY?通過AUTOLOAD,也許?什麼版本的DBI? – pilcrow 2013-02-22 22:36:51

+0

@pilcrow - (對不起,我以前沒有注意到您的評論。)DBI v1.623。我的代碼不會調用DESTROY或使用AUTOLOAD。這個過程似乎是完整的,Perl正在清理。我有一個信號處理程序捕獲異常並打印一個小堆棧跟蹤(caller()),它只顯示正在運行的陷阱例程,而不是從我的代碼(當它捕獲真正的錯誤時發生)。 – Allen 2013-03-04 16:09:15

回答

2

這裏是在黑暗中拍攝。

DBI數據庫句柄通常像任何其他對象一樣被銷燬 - 當沒有引用它們時。然而,事情可以防止把手被自然破壞:

  • 句柄是包全局循環引用的
  • 把手樣式一部分的Perl不能自動免費

發生這種情況時,對象作爲「全球破壞」的一部分被銷燬,它基本上只是取消所有的東西,並且實際上以隨機順序呼叫DESTROY。這可能是導致你虛假錯誤的原因。

首先,您可以嘗試在腳本的開始和結尾枚舉DB句柄,並查看是否有任何結尾仍在使用中。見this code snippet

如果你不知道爲什麼對象仍然在使用,你可以使用Devel::Cycle上一些大的數據結構來找到它們。

您可能還會發現DBI的tracing functionality有用。在運行腳本之前導出DBI_TRACE=2,每次創建或銷燬句柄時都會記錄日誌。

+0

謝謝,一個很好的答案,但不符合我的情況AFAIK,但我仍在考慮它。我試過數據庫跟蹤(),但它顯示正常處理。這似乎發生在我commit()和exit()之後;我期望Perl能夠正常清理它。該錯誤意味着DESTROY()缺少一個參數?這已經好幾年了,然後突然之間,這一天開始噴出這個消息。 – Allen 2013-03-04 16:22:43

+0

它應該在退出後清理,但它沒有(而是全局毀壞被完成),這意味着某些東西在保持數據庫句柄。全局破壞會解釋錯誤,因爲在調用析構函數之前dbh可能是未定義的(!)正如我所說的那樣,這些都是黑暗中的鏡頭。如果代碼沒有被更改,那麼DBD :: Pg可能已升級,或者您的數據庫配置(超時?)已被更改? – rjh 2013-03-05 10:58:12

1

在我的情況下,它升級服務器後開始發生,因此它似乎是一個PostgreSql/Perl/DBD版本特定的錯誤。

這個錯誤突然開始在我沒有明確銷燬數據庫句柄的所有腳本中引發。 加入$dbx->disconnect()解決了它。

更新:此解決方法僅在我的一些腳本中修復了錯誤。在其他情況下,當明確銷燬數據庫句柄時,錯誤也會持續存在。

相關問題