【故障公告】SQL語句執行超時引起網站首頁訪問故障

很是抱歉,今天早上 6:37~8:15 期間,因爲獲取網站首頁博文列表的 SQL 語句出現突發的查詢超時問題,形成訪問網站首頁時出現 500 錯誤,由此給您帶來麻煩,請您諒解。html

故障的狀況是這樣的。web

故障期間日誌中記錄了大量下面的錯誤。數據庫

2020-02-03 06:37:24.635 [Error] An unhandled exception has occurred while executing the request.
/
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware
System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
 ---> System.ComponentModel.Win32Exception (258): Unknown error 258
   at System.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__126_0(Task`1 result)

數據庫服務器(阿里雲 RDS SQL Server 2016 實例)的 CPU 消耗突增。api

數據庫服務器的 IOPS 暴增。緩存

經過阿里雲 RDS 控制檯的 CloudDBA 能夠查看到故障期間獲取首頁博文的 SQL 語句被執行了3萬屢次,執行這麼屢次是因爲查詢超時,沒法創建緩存,每次請求都要訪問數據庫。服務器

發現故障後,咱們經過阿里雲 RDS 的主備切換恢復了正常。性能

通過對故障的排查分析,鎖定的最大嫌疑對象是 SQL Server 參數嗅探(詳見園子裏的博文 什麼是 SQL Server 參數嗅探)。網站

對於這種由於重用他人生成的執行計劃而致使的水土不服現象,SQL Server 有一個專有名詞,叫「參數嗅探 parameter sniffing」。阿里雲

並且咱們找到了引起 SQL Server 參數嗅探問題的條件。spa

在咱們的 open api 中提供了獲取首頁博文列表的 web api ,但沒有限制能夠獲取的最大博文數,也就是下面的 ItemCount 參數(除了 open api ,其餘地方調用時 ItemCount 值都是 20 )。

SELECT TOP (@ItemCount)

假若有人調用 open api 時給 ItemCount 傳了一個很大的值,好比 20000 ,雖然調用的是一樣的 SQL 語句,但因爲 ItemCount 的值不一樣, SQL Server 可能會生成相差很大的執行計劃,對於 ItemCount 20000 性能比較好的執行計劃,對於 ItemCount 20 可能性能極差。若是查詢 ItemCount 20000 時生成的執行計劃被緩存下來,查詢 ItemCount 20 時繼續使用這個執行計劃,就會出現原本好好的 SQL 查詢忽然變得性能極差。咱們今天遇到的故障極可能就是這個緣由,並且故障時就一個 SQL 語句出現問題(正好就這個 SQL 查詢緩存了水土不服的執行計劃),其餘都正常,也驗證了這個猜想。

經過此次故障,咱們吸收的教訓是必定要在代碼中對 ItemCount 與 PageSize 的最大值進行限制,它不單單是帶來沒必要要的低性能查詢,並且可能會由於 SQL Server 參數嗅探問題拖垮整個數據庫。

相關文章
相關標籤/搜索