[Azure][SQL]注意 Azure SQL Database 的 Scale Up/Down 的時機點

當在雲端的世界中,面對資源不足的 Scale Up 應該是平常的事情,但對於 Azure SQL Database 可要注意一下了。

前一陣子因為產品開發了一些新功能,因此需要透過 BACPAC 發佈資料庫之後,進行一些因為欄位變更的資料調整處理,使得同時間要更動的資料不少,擔心 DTU 不足而造成相關程序過久,因此決定在執行相關語法的時候,先將資料庫的等級從原本的 S2 調整到 S4 ,想說放大四倍的 DTU ,應該可以讓執行時間縮短一點,但沒有想到卻引發了一些問題。

話說還記得在 2016/2017 年的時候,當時在測試 Azure SQL Database 的時候,有測試過當在不同的資料庫等級下效能的差異,當時發現如果都在 Standard 的版本下,資料庫等級從 S0 ←→ S3 之間調整,就會發現效能會有不同的變化,而原本保持的連線也都還是正常運作。但如果是從 Standard 和 Premium 這兩個之間作調整,那就可能會導致原本還在執行的 SQL 命令會造成中斷的現象了,所以當時因為這樣的測試結果,讓我們覺得可以很放心的去調整等級。

而此次我們是先把 S2 → S4 ,就發現一些原本正在執行的命令執行到一半就中斷了;而當我們發現有這樣問題的時候,要再從 S4 → S2 的時候,又會再發生一次中斷的狀況,因此我決定來測試看看,是否現在不同等級之間的調整,究竟是否會發生問題。

以下這個是我用來測試執行 10 分鐘的 SQL 語法,主要是讓指令可以跑一段時間,因此中間就用個 WAITFOR DELAY 的語法在中間延遲一下

-- 檢查是否存在
IF OBJECT_ID('T1') > 0
	DROP TABLE T1;

-- 建立範例資料表
CREATE TABLE T1( F1 INT IDENTITY(1,1) PRIMARY KEY, F2 DATETIME );

DECLARE @PTR INT = 0 ;

-- 每十秒填入一筆資料,整體執行 10 分鐘
WHILE @PTR < 60
BEGIN
	INSERT INTO T1( F2 ) VALUES ( GETDATE() ) ;
	WAITFOR DELAY '00:00:10';
	SET @PTR += 1 ; 
END

GO

 

當在執行這些語法的時候,我們分別嘗試透過 Portal 上來調整資料庫的等級,也試著使用類似以下的 T-SQL 指令來調整等級

ALTER DATABASE [demo] MODIFY (SERVICE_OBJECTIVE = 'S4');
GO

 

經過反覆多次的測試,不論採用哪一種方式來變更資料庫的等級,都會造成在執行測試語法的時候,會出現以下的錯誤

 

比較簡單的來說,就是執行的命令的這條 Connection ,如果正好再要變更的時候還在執行中的狀況,那麼該連線就會被中斷了。因此像上述的測試,我們並沒有特別用 Transaction 去包起來,因此就會變成會有部分資料有填入,部分是沒有的狀況。所以不論使用 T-SQL 或 Portal 上的調整,從測試的結果看起來,都沒有辦法確保正在執行中的命令會順利執行完畢。

 

而當我們再這次測試告一個段落,要來整理資料的時候,忽然又想到說,如果我們使用 Elastic Pool 的方式來設定的話,調整整個 Pool 的 EDTU 而不是單一個資料庫的 DTU 的話,是否有機會不造成既有的連線中斷呢 ? 我們反覆也測試幾次,但不論用甚麼樣的排列組合,很不幸的,既有的連線也都還是會被中斷。

 

因此從上述的測試過程中會發現,資料庫的 Scale Out 看起來是一件很麻煩的事情,它並沒有辦法像是 Web App 一樣,當監測到資源不足的時候,就可以自動或手動的去 Scale Up/Out ,不會造成任何問題。目前在資料庫 Scalue Up/Down 的測試中,不論用甚麼方式,都會造成既有還在執行的連線中斷,因此大家在選用 Azure SQL Database 的時候,還是要多去注意一下平常的資源耗用,免得當臨時有需要較高的資源時候,可能會造成一些正在執行的系統會有些異常,這個部分就要特別注意了。