天天看點

SQLServer · 最佳實踐 · TEMPDB的設計

tempdb和其他資料庫一樣以model庫為模闆建立,是一個全局資源,可供所有連接配接到執行個體的使用者使用,不同的是它在每次sql server啟動的時候都會被重新建立,它主要存儲三種對象:

使用者對象:包括使用者顯示建立的本地/全局臨時表、表變量、表值函數、遊标、臨時存儲過程等

内部對象:tempdb中具體的内部對象一般是不可見的,因為它們的meta資訊隻存于記憶體中并沒有harden,是以系統視圖也查詢不到,大體分為work table、work file、sort units三類

版本存儲:包括聯機索引、多活動結果集、after觸發器以及使用快照的隔離級别都會在tempdb存儲舊的行版本

了解了tempdb存儲了哪些東西就可以知道它對于整個執行個體的重要性,尤其是性能上的影響,一些高并發場景很容易凸顯問題。

比如在生産環境中出現這樣的場景——應用頻繁的建立和銷毀臨時表

SQLServer · 最佳實踐 · TEMPDB的設計

500+的session挂起,這時候業務已經無法正常提供服務了,每個session都在等pagelatch_up(lastwaittype)對應資源是 2:*:2(waitresource)。

sqlserver的 pagelatch:pagepatch是同步通路資料庫page的latch,sql server的bp裡每個資料頁(8k)都有一個對應的latch,要通路某個page必須首先獲得這個page的latch,pagelatch有很多種,如共享的pagelatch_sh,獨占的pagelatch_ex,更新的pagelatch_up。

waitresource 2:*:2 分别表示database_id,file_id,page_id 對應資源是tempdb的某個datafile第二個資料頁;了解sqlserver的存儲結構可以知道datafile的前幾個page是固定的系統page,第二個page既是固定的全局配置設定映射頁(gam),tempdb做統一區配置設定的時候會用到。

這個場景是因為對臨時表操作的并發過高,tempdb在系統頁上出現嚴重争搶導緻整個執行個體卡慢進而影響業務,是一個非常典型的場景,解決方法最好從tempdb的規劃設計入手。

tempdb的資料檔案和正常業務資料庫分開存儲,配置在不同的實體裝置上;日志檔案建議和資料檔案分開存儲,業務資料庫的日志檔案也建議這樣

當執行個體配置設定的cpu個數小于8時,資料檔案的個數調整到和執行個體綁定cpu個數一緻;當配置設定的cpu個數大于8且存在系統頁的闩鎖争搶時按照4的倍數增加檔案直到瓶頸不在闩鎖上

資料和日志檔案的最大空間根據實體裝置大小配置到最大值或者不限

盡量避免shrinking tempdb哪怕隻是某個file

啟用資料和日志檔案的自動增長,配置所有資料檔案的增長速度一緻、初始大小一緻;這裡還有一種說法是評估設定好應用所需的tempdb穩定空間不做自動增長或者靠監控在業務低峰主動調整,當然如果能做到這一點那是很好的,但這需要應用非常穩定并做過長時間測試能夠找準這個穩定空間并做好監控和主動擴容,在實際環境中這基本是很難達到的,是以配置自增長是在實際生産環境中更推薦的做法

如果不是實體裝置的空間或性能異常請保證隻有一個日志檔案

開啟trace flag 1118緩解sgam頁的争搶

dbcc traceon (1118, -1)

如果有這樣的場景:pagelatch_up對應資源都是同一個file(file_id相同),那麼可能是由于資料檔案大小非常不均衡使proportional fill algorithm一直在一個檔案上配置設定空間,這種情況可以考慮使用黑科技開啟trace flag 1117解決,但同時會造成空間消耗,因為這是執行個體級别的參數不止作用于tempdb,所有db的資料檔案都會統一增長

dbcc traceon (1117, -1)

最後,現實場景中即使對tempdb做好了規劃也不排除應用異常使用導緻的各種問題,是以合理的監控是必不可少的。

sqlserver針對tempdb提供了一些視圖資訊友善我們監控排查,主要了解sys.dm_db_file_space_usage、sys.dm_db_session_space_usage、sys.dm_db_task_space_usage這三個就可以幫我們做好監控。