2009-06-18 35 views
8

客戶端在執行存儲過程時報告了非常奇怪的行爲的重複實例。MS SQL Server 2005 - 存儲過程「自發中斷」

它們具有運行易失性數據集的高速緩存轉置的代碼。一個存儲過程寫來重新處理需求的數據集,如果:
1.數據集已經自上次再處理改變
2. datset一直不變5分鐘

(第二個條件期間停止大規模的重複重新計算變化的時代。)


這工作得很好了幾個星期後,SP正在採取1-2秒即可完成再處理,並在需要時只做到了。然後......

  • 的SP突然「停止工作」(它只是不停地奔跑,再也沒有回來)
  • 我們以一種微妙的方式改變了SP和它
  • 幾天後再次合作就停止再次合作,然後
  • 有人說:「我們已經看到在此之前,剛剛重新編譯SP」
  • 在不改變我們重新編譯了SP的代碼,它的工作
  • 幾天後它停止工作了


這已經重複很多次。 SP突然「停止工作」,從不返回,客戶超時。 (我們嘗試通過管理工作室運行它,並在15分鐘後取消了查詢。)

然而,每次我們重新編譯SP時,它都會突然再次運行。

我還沒有在適當的EXEC語句上嘗試WITH RECOMPILE,但我不特別想這樣做。它每小時調用一百次,通常不做任何事情(它只能每天重複處理數據)。如果可能的話我想避免重新編譯的是一個相對複雜的SP的開銷「,只是爲了避免一些東西,‘不應該’發生......


  • 有沒有人在此之前經歷?
  • 有沒有人對如何克服它什麼建議嗎?


乾杯,
Dems。


編輯:

的pseduo代碼將如下所示:

  • 讀取的 「a」 從TABLE_X
  • 讀 「B」 從TABLE_X
  • 如果(a < b)返回
  • BEGIN TRANSACTION
  • DELETE table_y
  • INSERT INTO table_y < 3選擇聯合在一起>
  • UPDATE TABLE_X
  • COMMIT TRANSACTION

的選擇是 「不漂亮」,但是當在線中執行他們立即執行。包括當SP拒絕完成時。並且剖析器顯示它是INS在SP處「掛起」的位置

SP沒有參數,sp_lock也沒有顯示任何阻止該過程的參數。

+2

聽起來像你有一個事務沒有被提交或回滾。很難說沒有看到代碼。 – Juliet 2009-06-18 21:24:26

+0

哦,它並不會傷害到下載最新的服務包和upates。 – Juliet 2009-06-18 21:26:28

+0

它必須是LOCK,或者至少表現如此...... – tekBlues 2009-06-18 21:29:56

回答

1

正如其他人所說,一些有關數據或源表的統計數據正在改變導致緩存的查詢計劃過時。

WITH RECOMPILE可能是最快的修復方法 - 使用SET STATISTICS TIME ON來查明重新編譯開銷的實際情況,然後再解除它。

如果這仍然不是一個可接受的解決方案,最好的選擇可能是嘗試重構插入語句。

你不說在插入語句中是否使用UNIONUNION ALL。我見過INSERT INTOUNION產生一些奇怪的查詢計劃,特別是在2005年SQL

  • SP2之前的版本中刪除和 與 SELECT INTO重新創建目標表的Raj的建議是一條路可走。

  • 您也可以嘗試在插入選擇每個 三個源查詢到自己的 臨時表,然後UNION這些臨時表 在一起。

  • 或者,你可以嘗試這些建議一個 組合 - 把工會的結果爲 臨時表SELECT INTO, 然後從插入到目標 表。

我見過所有這些方法都可以解決類似場景下的性能問題;測試會揭示哪些數據會給您帶來最好的結果。

3

這是參數嗅探的足跡。是的,第一步是嘗試RECOMPILE,雖然它並不總是按照您希望的方式工作於2005年。

更新: 我會嘗試在INSERT語句級重新編譯,因爲這可能是一個統計信息問題(哦,是的,檢查自動更新統計信息)。

如果這看起來不符合參數嗅探,那麼比較實際查詢計劃從何時工作正常以及從何時運行到永久(使用估計計劃,如果無法獲得實際值,但實際值會更好)。您正在查看計劃是否更改。

3

我完全同意參數嗅探診斷。如果你對SP有不同的輸入參數(或者即使它們不變),一定要用局部變量掩蓋它們,並使用SP中的局部變量。

如果集合正在更改但查詢計劃不再適用,也可以使用WITH RECOMPILE

在SQL Server 2008中,您可以使用OPTIMIZE FOR UNKNOWN功能。另外,如果你的過程涉及填充一個表格,然後在另一個操作中使用該表格,我建議把這個過程分解成單獨的SP並分別調用它們。WITH RECOMPILE。我認爲,當您填充表格並使用該表格的結果執行操作時,流程開始時生成的計劃有時可能非常差(如此糟糕以至於無法完成)。因爲在最初的計劃時,表格與初始插入後有很大不同。

0

很明顯,通過重新編譯來更改存儲過程會改變導致鎖定的情況。

嘗試按herehere所述記錄SP的進度。

0

如果你是做下列步驟操作:

DELETE table_y 
INSERT INTO table_y <3 selects unioned together> 

你可能想試試這個,而不是

DROP TABLE table_y 
SELECT INTO table_y <3 selects unioned together> 
0

我同意在評論中給出的答案,這聽起來像一個未關閉的事務,特別是如果您仍然能夠從查詢分析器運行select語句。

聽起來很像是有一個打開的事務,並且有一個掛起的table_y刪除操作,插入無法在此時發生。

當您的SP鎖定時,是否可以在table_y中執行插入操作?

0

你有索引維護工作嗎?

你的統計數據是最新的?一種方法是檢查大型變體的估計和實際查詢計劃。

0

正如其他人所說,這聽起來很可能是一個未承諾的交易。

我最好的猜測:

你要確保table_y可以完全和迅速刪除。

如果還有其他存儲過程或外部代碼段在此表上保存事務,則可能會一直等待。 (他們可能會出錯並且永遠不會關閉交易)

另一個注意事項:如果可能,請嘗試使用truncate。它使用較少的資源比沒有where子句一個刪除:

truncate table table_y 

而且,一旦出錯你自己的事務中發生,這將導致所有下列電話(每5分鐘顯然)「掛起」,如果不予處理你的錯誤:

begin tran 
begin try 
-- do normal stuff 
end try 
begin catch 
rollback 
end catch 
commit 

第一個錯誤是什麼會給你關於實際錯誤的信息。看到它掛在你自己的後續測試只是一個次要的影響。

相關問題