往期分享
RDS MySQL
RDS MySQL 執行個體空間問題 RDS MySQL 記憶體使用問題 RDS MySQL 活躍線程數高問題 RDS MySQL 慢SQL問題 RDS MySQL 執行個體IO高問題 RDS MySQL 小版本更新最佳實踐RDS PostgreSQL
RDS PostgreSQL 執行個體IO高問題 RDS PostgreSQL 慢SQL問題 RDS PostgreSQL CPU高問題RDS SQL Server
RDS SQL Server 磁盤IO吞吐高問題 RDS SQL Server CPU高問題概述
執行個體的空間使用率是RDS SQL Server使用者日常需要重點關注的監控項之一。如果執行個體的存儲空間完全打滿,将會導緻嚴重的影響,包括:資料庫無法寫入、資料庫備份無法正常完成、存儲空間擴容任務的執行耗時可能更長等。
一般來說,當一個RDS SQL Server執行個體的存儲空間使用比例達到80-85%以上時,就應及時進行處理,要麼降低資料庫實際占用空間的大小,要麼對存儲空間進行擴容,以避免空間打滿的風險。
檢視空間使用情況
RDS控制台
RDS SQL Server的控制台中提供了多種檢視執行個體空間使用情況的方法:
基本資訊
在RDS控制台的“基本資訊”頁中會顯示執行個體的總存儲空間使用大小,但這裡隻有目前的空間使用總量,沒有具體的各類資料分别占用空間大小的資訊,也沒有空間使用的曆史資訊。

監控與報警
在RDS控制台的“監控與報警”頁中的“标準監控”->“資源監控”下,可以檢視執行個體的各類資料占用的磁盤空間大小的資訊,并且會顯示各部分空間大小的曆史變化曲線。
其中磁盤空間總體使用量即對應目前執行個體實際已經使用了的所有存儲空間總量,它由如下四個部分組成:
資料空間使用量 | 所有使用者資料庫的資料檔案(mdf和ndf檔案)總大小。 |
日志空間使用量 | 所有使用者資料庫的日志檔案(ldf檔案)總大小。 |
臨時檔案空間使用量 | 系統資料庫tempdb的所有資料檔案和日志檔案的總大小。 |
系統檔案空間使用量 | 系統資料庫master、msdb和model的所有資料檔案和日志檔案,以及SQL Server執行個體目錄下的一些系統檔案(錯誤日志、default trace、系統擴充事件檔案等)的總大小。 |
CloudDBA
在RDS控制台的“CloudDBA”->“空間管理”頁中可以檢視執行個體内更詳細的空間使用情況,包括資料與日志的空間使用對比、空間使用的曆史變化趨勢、Top資料庫和Top表的空間配置設定明細等。
這裡的“總空間”、“已使用”和“可用空間”均是針對每個資料庫的所有資料檔案和日志檔案的空間總和。
而在“TOP 20資料表”這個清單中的統計,則是針對資料庫中的表所使用的資料檔案空間。其中“保留大小”為“資料空間”、“索引空間”、“未使用空間”三部分之和,它們的具體含義如下:
保留大小 | 已保留給該表的所有空間總和,包括資料、索引及未使用的部分 |
資料空間 | 表中的資料使用的總空間 |
索引空間 | 表中的所有索引使用的總空間 |
未使用空間 | 已保留給該表但還未配置設定使用的空間 |
用戶端工具
對于RDS SQL Server來說,使用SQL Server用戶端工具連接配接到執行個體上之後直接檢視執行個體的空間使用資訊,也是很友善的。
SQL腳本
以下是一些常用的檢視SQL Server資料庫空間使用資訊的系統視圖或指令:
sp_helpdb | 檢視所有資料庫各自的總空間大小(資料檔案與日志檔案大小之和) |
DBCC SQLPERF(LOGSPACE) | 檢視所有資料庫各自日志檔案的總空間大小以及實際已使用部分的大小 |
sys.master_files | 檢視所有資料庫的所有資料和日志檔案各自的大小 |
sys.dm_db_log_space_usage | 檢視目前資料庫的日志檔案的總空間大小以及實際已使用部分的大小 注:适用于SQL Server 2012以上版本 |
sys.dm_db_file_space_usage | 檢視目前資料庫的所有資料檔案各自的總空間大小以及實際已使用部分的大小 |
DBCC SHOWFILESTATS | |
sp_spaceused | 檢視目前資料庫的總空間大小、已使用空間大小 檢視目前資料庫的資料檔案的保留白間、資料空間、索引空間及未使用空間大小 檢視指定表的保留白間、資料空間、索引空間及未使用空間大小 |
SSMS工具UI
SQL Server Management Studio用戶端工具中提供了一些基本的檢視資料庫空間使用資訊的報表,也可以幫助使用者比較友善的分析單個資料庫内的空間配置設定使用情況。
空間回收與釋放
當遇到執行個體的空間使用率過高問題時,應首先從RDS控制台的監控與報警頁中檢查一下資料、日志、臨時檔案、系統檔案各部分的空間使用情況,看下是哪部分的空間使用占比較高或增長速度較快,并進一步評估能否采取措施釋放出部分空間或避免空間的快速增長。
對于資料空間占比較高的情況,可首先通過CloudDBA空間管理頁或sys.master_files等系統視圖檢查是哪些資料庫的資料空間較大,其中CloudDBA中還可以檢視空間使用變化的曆史曲線,使用起來更為友善。
對于每個資料庫來說,其資料空間的總大小(即其所有資料檔案大小的總和)是由已配置設定的(Allocated)和未配置設定的(Unallocated)兩部分組成的。其中未配置設定的部分是由完全未配置設定的Extent(每個為連續的64KB空間)構成的,不和任何資料庫對象關聯,也隻有這部分空間有可能通過檔案收縮的方式釋放出來給作業系統。而已配置設定的部分通常都是和特定的資料庫對象關聯的,其中又包括已使用的(Used)和未使用的(Unused)部分,未使用的部分通常隻能配置設定給同一表或索引新增的記錄使用,而無法被其他不同的對象直接使用。
在資料庫中的資料量持續增長的情況下,資料檔案中的未配置設定部分通常都是很小的,這也就意味着在未對資料庫空間的使用主動進行優化之前,直接嘗試收縮資料檔案的大小一般不會有什麼效果。大部分情況下,若需要控制資料空間的增長并進一步降低其大小的話,都應首先對已配置設定部分的空間使用進行優化和回收,然後再考慮進行資料檔案大小的收縮。
資料空間的回收
資料空間的回收通常主要有如下幾種方式:
資料歸檔
将資料庫表中不常用的資料(例如早期的曆史資料)從目前表中清除掉,并可根據需要轉移到其他資料庫執行個體中,或以其他形式進行歸檔儲存,通過直接減少資料量來降低目前資料庫對空間使用的需求。
這種方式如果可行的話,往往是控制資料空間增長量的最有效手段,但它通常對于資料庫對象結構及相關應用邏輯的設計也有一定的要求,需要應用設計和開發人員的參與配合。
資料壓縮
SQL Server企業版及2016以上的所有版本中提供了内置的資料壓縮的功能,使用者可以在單個表、索引或其分區上開啟壓縮功能,并且有行壓縮和頁壓縮兩種選項。具體功能說明和使用方法可參見:
https://docs.microsoft.com/en-us/sql/relational-databases/data-compression/data-compression資料的壓縮比和表結構、列的資料類型及數值分布情況等都有很大的關系,從百分之幾到90%以上都有可能。SQL Server中提供了一個專用的存儲過程sp_estimate_data_compression_savings可以幫助快速評估在指定的表或索引上開啟行壓縮或頁壓縮可以節省多大的存儲空間:
https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-estimate-data-compression-savings-transact-sql修改表或索引上的壓縮選項設定是一個DDL操作,如果是在SQL Server企業版中執行,可以使用ONLINE=ON參數線上的執行,基本不會影響表上的DML操作的正常執行。而如果是在SQL Server标準版或Web版中,由于不支援ONLINE DDL,對于大表執行此類操作将會造成長時間鎖表的情況,并可能對業務中的正常資料庫通路造成較大影響,通常應放在維護視窗内執行。
通過在表上開啟資料或索引壓縮來節省存儲空間的方式對資料庫應用來說是完全透明的,并且還可以提升資料緩存的效率和降低記憶體壓力,但同時往往也會增加資料存取操作過程中的CPU開銷,是以其對資料庫整體性能的影響是需要根據具體環境具體評估的。如果執行個體的CPU資源方面沒有瓶頸,而存儲空間和緩存壓力較大的話,則在主要的大表上啟用資料壓縮往往是一個比較好的優化選項。
索引碎片整理
當表中的索引的碎片率較高時,除了會降低索引掃描等操作的執行效率,往往還會導緻實際占用的存儲空間更大。從回收資料空間的角度考慮,對表上的索引執行碎片整理的操作也是一個可行的手段。
CloudDBA的“性能優化”->“索引使用率”頁中提供了對資料庫中的各表上的索引碎片率統計的結果,并相應的會給出索引重建(Rebuild)或重組(Reorganize)操作的建議:
此外,SSMS工具中自帶的Index Physical Statistics報表也提供了類似的功能:
不過需要注意的是,這裡的索引碎片率統計的是邏輯上相鄰的索引頁在實體位置上不一緻的情況的比例,和索引頁中的空閑空間比例并不是一個概念,隻不過碎片率較高的索引往往也有較大的機會是可回收空間比例較大的索引。如果要分析某個索引的頁内平均空閑空間比例的話,可以查詢系統視圖sys.dm_db_index_physical_stats并使用SAMPLED或DETAILED模式,然後參考結果集中avg_page_space_used_in_percent列的值。同時還要注意的是使用SAMPLED或DETAILED模式查詢視圖sys.dm_db_index_physical_stats時,會産生大量的索引頁讀取,并可能對資料庫性能造成一定影響,應謹慎操作:
https://docs.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql對于索引碎片的整理,SQL Server中提供了索引重建(Rebuild)和索引重組(Reorganize)兩種操作方式。其中Rebuild的方式往往優化效果更好,對于碎片率高的情況執行效率更高,預設情況下執行過程中會鎖表,但在企業版中可以啟用Online的模式避免長時間鎖表的影響。而Reorganize的操作總是以Online的方式進行,在碎片率較低的情況下執行效率會好一些,但碎片整理的優化效果相對不如Rebuild。
關于碎片整理的更多詳細說明,可以參考如下文檔:
https://docs.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes最後,與通過資料壓縮進行空間回收的方式不同,雖然通過索引碎片整理往往頁可以從資料檔案内回收出來一些存儲空間,但這個空間使用的減少可能隻是臨時性的,如果表上仍一直有較頻繁的插入和更新操作,那麼在清理完索引碎片後,索引碎片率及索引頁内的空閑空間比例很可能會快速上升,并導緻索引整體存儲空間占用的快速增長。是以通過索引碎片整理來控制資料空間增長的方法,主要還是适用于那些很少再更新的歸檔資料表,或者作為一種臨時的空間壓力緩解手段。另外,在對大表執行索引重建或重組的過程中,往往會産生大量的事務日志的寫入,這期間也要特别關注日志檔案大小增長的情況。在RDS SQL Server執行個體上開啟了每30分鐘日志備份選項的情況下,通常是可以比較及時的通過日志備份來回收和複用日志檔案中的空間的。
資料檔案的收縮
從避免執行個體的資料空間大小持續過快增長的角度考慮,通過上述方式達成了資料空間回收的效果通常就可以了,因為回收出來的空間就可以繼續提供給新的資料空間配置設定需求使用了,而不會造成資料檔案大小的持續增長。
但如果确有必要的話,也可以在資料庫中執行DBCC SHRINKFILE指令來對資料檔案進行收縮,進而将資料檔案中未配置設定的空閑部分空間釋放給作業系統,減少整個執行個體實際占用的磁盤空間大小。
使用DBCC SHRINKFILE指令來對指定的資料檔案進行收縮之前,可以先使用DBCC SHOWFILESTATS指令檢視各資料檔案的大小及其中實際已配置設定使用部分的大小,已使用的部分是無法被收縮掉的。
以上圖中的執行結果為例,一個Extent的大小為64KB,是以ID為1的資料檔案的總空間大小為104584MB,其中已使用的部分大小為82089MB,則該資料檔案通過收縮操作可以縮到的最小大小不會低于82089MB。
若要将該資料檔案的大小縮小到90000MB,則可以執行如下指令:
DBCC SHRINKFILE(1, 90000)
關于檔案收縮操作的更多詳細說明,可以參考如下文檔:
https://docs.microsoft.com/en-us/sql/relational-databases/databases/shrink-a-database https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-shrinkfile-transact-sql另外要注意的是,資料檔案的收縮是一個資源開銷較高的操作,會在資料檔案上産生大量的磁盤IO,并且還會産生大量的事務日志寫入,是以一般應盡量放在執行個體的負載較低的時候執行。
日志空間
日志空間的回收相對比較簡單,首先可以使用DBCC SQLPERF(LOGSPACE)指令或CloudDBA空間管理頁檢視是哪些資料庫的日志檔案較大,以及這些庫的日志檔案中實際已使用部分的比例。
例如,以上資料庫db02的日志檔案大小為2312MB,其中已使用的部分比例為99%,這時如果對該資料庫的日志檔案進行收縮,則幾乎不會有任何效果。
這種情況下可首先查詢系統視圖sys.databases,通過其中log_reuse_wait/log_reuse_wait_desc列的輸出資訊來判斷是什麼原因導緻事務日志檔案中的空間無法被回收:
關于log_reuse_wait/log_reuse_wait_desc列的各種取值含義的具體說明詳見如下文檔:
https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql其中最常見的一種情況就是LOG_BACKUP。在RDS SQL Server中,資料庫預設都是用的完整恢複模式,這種情況下日志檔案中記錄的内容不會被自動截斷(即使事務已送出),而隻有完成日志備份的部分才可以被截斷和回收複用。另外由于SQL Server日志檔案循環寫入的結構特點,最多會需要完成兩次日志備份之後,已截斷部分的日志檔案空間才可以被收縮掉。
RDS SQL Server中内置了自動備份的功能,通常每天會自動做一次全量或差異資料備份,并且在資料備份完成後還會自動做一次日志備份。同時在預設設定下,還會每30分鐘自動做一次日志備份,進而保障事務日志中的空間可以被及時回收複用。此外在每天一次的資料+日志備份完成之後,還會自動對日志檔案執行一次收縮操作,這樣即使有一些臨時的情況(例如大表的索引重建等大事務)導緻日志檔案的大小臨時增長到很大,通常也會在一天之内恢複到較小的狀态。
是以絕大部分情況下,使用者沒有必要主動對RDS執行個體上的資料庫執行日志檔案收縮的操作。另外由于RDS使用者沒有直接執行資料庫或日志備份操作的權限,是以如果出現日志複用等待類型為LOG_BACKUP情況,使用者也無法通過先執行BACKUP LOG再執行DBCC SHRINKFILE操作的方式來對日志檔案大小進行收縮。
如果确實遇到必須盡快對日志檔案大小進行收縮的情況,例如日志檔案的增長已經過大導緻磁盤可用空間過低,且無法等到下一次的每天定時備份時自動對日志檔案進行收縮。則使用者可以從RDS控制台的備份恢複頁中執行“收縮事務日志”的操作,這時RDS會自動對所有的使用者資料庫執行事務日志備份及日志檔案收縮的操作。
由于事務日志的收縮需要先等待日志備份操作的完成,是以如果執行該操作時資料庫中還有大量未備份過的日志,則日志檔案的收縮仍需要等待較久的時間才能完成。
臨時檔案空間
臨時檔案空間指的是SQL Server中的系統資料庫tempdb占用的空間大小。由于tempdb庫總是使用簡單恢複模式,是以其日志檔案增長到很大的情況是很少見的。但tempdb庫的資料檔案增長到很大的情況則較為常見,如大量臨時表的使用、大表連接配接或排序操作、大量基于快照的row versioning資料等都可能導緻tempdb庫資料檔案空間的大量使用。
檢視資料庫空間使用情況的指令如DBCC SHOWFILESTATS等對于tempdb庫也是适用的。但是在很多情況下,即使在tempdb庫中顯示有大量未使用的空間,通過DBCC SHRINKFILE指令也無法有效的将其收縮到很小。并且在RDS中預設也沒有授予使用者直接通路tempdb庫的權限,是以使用者也無法直接對tempdb庫執行檔案收縮的操作。
是以針對tempdb庫空間占用過大的情況,一方面可盡量從資料庫應用層面規避,如減少不必要的臨時表的使用、減少不必要的大表連接配接查詢、避免資料庫中有長事務等;另一方面就是當tempdb庫增長到較大時,可以安排合适的時間對RDS執行個體執行一次重新開機操作,SQL Server服務重新開機之後,tempdb庫會恢複到執行個體建立之初時的大小。
關于SQL Server中的tempdb資料庫空間使用情況的監控與分析,可以參考如下連結:
https://www.mssqltips.com/sqlservertip/4356/track-sql-server-tempdb-space-usage/系統檔案空間
系統檔案空間包括系統資料庫master、msdb和model的所有檔案,以及SQL Server執行個體系統目錄下的一些檔案,如錯誤日志、default trace、系統擴充事件檔案等。
通常情況下,以上這些檔案都不會很大,一般加在一起也不會超過幾百MB。但有些情況下,SQL Server的錯誤日志檔案大小增長到幾GB甚至更大也是有可能的。
例外一種可能導緻系統檔案空間增長到很大的情況,就是SQL Server服務在運作過程中遇到了嚴重的異常時自動産生的記憶體轉儲(memory dump)檔案,這通常意味着可能遇到了SQL Server産品中的bug。雖然這種問題發生的幾率不高,但如果出現是有可能導緻短時間内生成較多的dump檔案并占用較大的磁盤空間的。
對于RDS使用者來說,無法直接獲知各類系統檔案實際占用的磁盤空間的大小。如果在監控中發現系統檔案空間使用過高的情況,可送出工單聯系阿裡雲售後幫助檢查具體的原因。
存儲空間擴容
當出現RDS執行個體存儲空間使用率過高,且參考上述說明評估後發現無法有效降低空間使用大小的情況下,應及時對執行個體進行存儲空間的擴容。
各版本的RDS SQL Server執行個體在執行存儲空間擴容時的操作方式都是一樣的,即直接從RDS控制台上發起“變更配置”的操作,并指定擴容後存儲空間大小及切換時間規則:
但是由于不同版本的RDS SQL Server執行個體在底層架構上的差異,其存儲空間擴容任務執行的機制及變配所需時間也有所不同。
- RDS SQL Server 2008 R2本地盤版高可用版
由于采用多執行個體共享同一實體主機上的本地磁盤的模式,在做存儲空間擴容時,如果本地磁盤可用空間充足,則任務可在1分鐘以内完成,并且不會造成任何資料庫通路的中斷。
但如果本地磁盤空間不能滿足擴容要求的話,則會産生跨機遷移的任務,根據執行個體資料量大小的不同,整個任務的執行用時在20分鐘到1-2天不等,其中切換時的資料庫通路中斷時間一般不超過30秒。
- RDS SQL Server 2008 R2及以上雲盤版高可用版
對于雲盤版執行個體來說,無法直接線上的完成存儲空間的擴容,但是也無需在執行個體或主機之間進行資料的遷移。存儲空間擴容任務的執行過程,是首先在備執行個體上将作業系統關機并進行雲盤空間的快速擴容,然後啟動備執行個體,待主備資料同步之後進行主備切換,最後在新的備執行個體(即原主執行個體)上重複同樣的過程。
上述過程中的整體用時一般在10-20分鐘之間,其中切換時的資料庫通路中斷時間一般不超過30秒。
- RDS SQL Server 2012及以上雲盤版單機版
對于單機版執行個體來說,為進一步确儲存儲空間擴容過程中的資料可靠性,在正式開始變配任務執行前會先對執行個體上的資料庫做一次臨時備份(通常為增量備份),之後是将執行個體的作業系統關機并進行雲盤空間的快速擴容,最後啟動執行個體并等待資料恢複完成。
視具體情況的不同,正式開始變配操作前等待臨時備份完成的時間從幾分鐘到幾小時不等,變配過程中資料庫通路中斷的時間一般在幾分鐘到十幾分鐘之間。