數據庫常常遇到的問題:html
1)、數據庫文件空間用盡 2)、日誌文件不停增加 3)、數據庫文件沒法收縮 4)、自動增加和自動收縮java
本系列就以上面的4個問題入手分析並總結數據庫空間的管理方法。數據庫
一、文件的分配方式以及文件空間檢查方法服務器
首先,你在你的數據庫中運行sp_spaceused;以後會看到當前數據庫的使用空間信息;這個命令也就會將大概的數據庫空間信息給你展示出來,並不能查看每一個數據文件和日誌文件的使用狀況;其中對於數據庫tempdb來講裏面存儲的臨時數據對象,這個命令是統計不到的。咱們知道數據庫分爲主文件(.mdf)和輔助文件(.ndf);數據的存放按照頁和區來存放和管理的,這裏有一條命令能夠查看具體的頁內容:DBCC PAGE (<db id >,<file id >,<page id>,<format id>)咱們來運行這個命令前打開跟蹤標誌(trace flag):oracle
上圖使用參數爲3的命令,下面咱們設置參數爲2:看看輸出的信息,裏面的信息結合Sql Server專題一:索引(上)的內容即可理解,下面的內容其實就將222的數據頁內的內容給展示出來了;補充(與下文無關):SQL Server會將總長超過8K的的數據頁分開存放,單獨放在行溢出(Row-Overflow)頁中.
post
PAGE: (1:222)
BUFFER: BUF @0x00000001F07A2F40 bpage = 0x00000001E1068000 bhash = 0x0000000000000000 bpageno = (1:222) bdbid = 5 breferences = 0 bcputicks = 0 bsampleCount = 0 bUse1 = 7102 bstat = 0x9 blog = 0x2121215a bnext = 0x0000000000000000 PAGE HEADER: Page @0x00000001E1068000 m_pageId = (1:222) m_headerVersion = 1 m_type = 2 m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x200 m_objId (AllocUnitId.idObj) = 34 m_indexId (AllocUnitId.idInd) = 2 Metadata: AllocUnitId = 562949955649536 Metadata: PartitionId = 562949955649536 Metadata: IndexId = 2 Metadata: ObjectId = 34 m_prevPage = (1:221) m_nextPage = (1:223) pminlen = 10 m_slotCnt = 137 m_freeCnt = 38 m_freeData = 7880 m_reservedCnt = 0 m_lsn = (33:400:6) m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = -639233702 DB Frag ID = 1 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = NOT ALLOCATED PFS (1:1) = 0x40 ALLOCATED 0_PCT_FULL DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED DATA: Memory Dump @0x000000000F89A000 000000000F89A000: 01020000 00020200 dd000000 01000a00 df000000 .................... 000000000F89A014: 01008900 22000000 2600c81e de000000 01000000 省略 ............ 000000000F89BFF4: 90015c01 1001be00 86006000 ..\.......`. OFFSET TABLE: Row - Offset 136 (0x88) - 7826 (0x1e92) 135 (0x87) - 7792 (0x1e70) 134 (0x86) - 7720 (0x1e28) 133 (0x85) - 7636 (0x1dd4) 125 (0x7d) - 7174 (0x1c06) 118 (0x76) - 6802 (0x1a92) 省略 ............ 5 (0x5) - 400 (0x190) 4 (0x4) - 348 (0x15c) 3 (0x3) - 272 (0x110) 2 (0x2) - 190 (0xbe) 1 (0x1) - 134 (0x86) 0 (0x0) - 96 (0x60) DBCC 執行完畢。
另外一種查看數據庫的方法是:在Mangement Studio中選擇數據,右鍵-->報表-->標準報表中查看:這兩種統計的方法是不一樣的;這裏是按照區來統計的;上面的sp_spaceused使用的是頁統計方法;報表這種方法內部是調用了DBCC SHOWFILESTATS命令,這個命令直接從GAM和SGAM這樣的系統分配頁面上讀取區的分配信息,直接算出數據庫文件裏面有多少區被分配了;由於SQL Server絕大多數是按照區爲單位來分配新的空間的,而系統分配頁上的信息是實時更新的,因此這個統計方法比較可靠;在服務器負載很高的狀況下也能夠執行;因此不推薦sp_spaceused的方法,這種方法還不如查看系統試圖(sys.dm_db_partition_stats);性能
其實還有一種查看數據空間的方法:DBCC SHOWCONTIG(或者 sys.dm_db_index_physical_stats)這個命令能夠統計出你的某張表或者索引用了多少頁面、多少區、甚至頁面的平均數據量。從這些值你能夠算出一張表格佔用了多少空間。這個命令的代價恨到,SQL Server會掃描數據庫,而掃描的過程是要加鎖的;例如sys.dm_db_index_physical_stats就有三種掃描方式。越精確掃描越久。1:LIMITED 2 : SAMPLED 3 : DETAILED這3中方式掃描時間依次增長; 下面爲DBCC SHOWCONTIG的統計信息。這種信息對於統計區的使用狀況、碎片程度展示比較好。url
DBCC SHOWCONTIG 正在掃描 'DimAccount' 表... 表: 'DimAccount' (5575058);索引 ID: 1,數據庫 ID: 8 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 2
- 掃描區數..............................: 1
- 區切換次數..............................: 0
- 每一個區的平均頁數........................: 2.0
- 掃描密度 [最佳計數:實際計數].......: 100.00% [1:1] - 邏輯掃描碎片 ..................: 50.00% - 區掃描碎片 ..................: 0.00% - 每頁的平都可用字節數.....................: 2695.0
- 平均頁密度(滿).....................: 66.70% DBCC SHOWCONTIG 正在掃描 'DimCurrency' 表... 表: 'DimCurrency' (21575115);索引 ID: 1,數據庫 ID: 8 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 1
- 掃描區數..............................: 1
- 區切換次數..............................: 0
- 每一個區的平均頁數........................: 1.0
- 掃描密度 [最佳計數:實際計數].......: 100.00% [1:1] - 邏輯掃描碎片 ..................: 0.00% - 區掃描碎片 ..................: 0.00% - 每頁的平都可用字節數.....................: 3147.0
- 平均頁密度(滿).....................: 61.12% DBCC SHOWCONTIG 正在掃描 'DimCustomer' 表... 表: 'DimCustomer' (37575172);索引 ID: 1,數據庫 ID: 8 已執行 TABLE 級別的掃描。 - 掃描頁數................................: 1569
- 掃描區數..............................: 197
- 區切換次數..............................: 1238
- 每一個區的平均頁數........................: 8.0
- 掃描密度 [最佳計數:實際計數].......: 15.90% [197:1239] - 邏輯掃描碎片 ..................: 75.27% - 區掃描碎片 ..................: 3.05% - 每頁的平都可用字節數.....................: 3037.7
- 平均頁密度(滿).....................: 62.47% 省略…… DBCC 執行完畢。若是 DBCC 輸出了錯誤信息,請與系統管理員聯繫。
附加:日誌文件 spa
咱們知道日誌文件不是按照頁、區來分配和管理的。SQL Server 數據庫引擎在內部將每一物理日誌文件分紅多個虛擬日誌單元。虛擬日誌單元沒有固定大小,而且一個物理日誌文件所包含的虛擬日誌單元數十部固定的。管理員不能配置或設置虛擬日誌單元的大小或數量。但 SQL Server 會嘗試控制虛擬日誌單元的數目,把它限制在一個合理的範圍裏。例外狀況是,日誌文件每字段增加一次,會至少增長一個虛擬日誌單元。因此,若是一個日誌文件經歷了屢次自動增加,裏面的虛擬日誌單元數目會比正常的日誌文件多不少,這種狀況會影響日誌文件管理的效率,以致於影響SQL Server 的啓動。事務日誌是一種迴繞的文件。另外,這裏有一篇專門介紹SQL Server的日誌的博客。下圖爲事務日誌的工做方式;日誌
最後:瞭解了文件的分配和檢查再加上對索引的瞭解,咱們下面就解決第一個和第三個問題:1)、數據庫文件空間用盡 。3)、數據庫文件沒法收縮
首先若是出現此種問題,管理員首先會想到將數據文件收縮或者清空。通常有兩種命令能夠選擇: 1】. DBCC SHRINKDATABASE 2】. DBCC SHRINKFILE 因爲DBCC SHRINKDATABASE一次運行同時影響全部的文件(包括數據文件和日誌文件),使用者不能指定每一個文件的目標大小,其結果可能不能達到預期要求。因此建議仍是作好規劃,對每一個文件肯定預期目標,而後使用DBCC SHRINKFILE來一個個的處理。通常收縮數據文件的狀況會比較多,可是,首先要了解:
1.文件當期的使用狀況,收縮量的大小不可能超過當前文件的空閒空間大小。若是想要壓縮數據庫的大小,首先就要確認數據文件的確有相應未被使用的空間。若是空間都在使用中,那就要先確認大量佔用空間的對象。而後經過歸檔歷史數據,先把空間釋放出來;
2.主數據文件是不能被清空的,能被清空的只有輔助數據文件。
3.若是要把一個文件組整個清空,要刪除分配在這個文件組的對象,或者把他們移到其餘文件組上 DBCC SHRINKFILE是不能幫你作到這些的。
把數據文件裏面該清除的數據和對象清除完、確認數據文件有足夠的空閒空間後,管理員就能夠下 DBCC SHRINKFILE命令來縮小或清空指定文件了。若是是要全部文件,就要填上tearget_size,若是是要清空文件,就選擇EMPTYFILE。SQL Server 在作 DBCC SHRINKFILE的時候,會掃描數據文件並對正在讀的頁面加鎖,因此對數據庫的性能會有所影響。可是這不是一個獨佔的行爲。在作 DBCC SHRINKFILE的時候,其餘用戶照樣能夠對數據庫進行讀寫操做。能夠在進程的任何一點中止 DBCC SHRINKFILE操做。
但是,有時候,明明看到數據文件裏面有空間,爲啥就是不能壓縮或者清空?這是由於數據文件裏面雖然有不少空的頁面,可是這些頁面分散在各個區裏,使得整個文件沒有不少空區。須要說明的是, DBCC SHRINKFILE作的都是區一級別的動做。他會把使用過的區前移,把沒有使用過的區從文件中移除。可是,他不會把一個區裏面的空頁移除、合併,也不會把頁裏面的空間移除、合併。因此一個數據庫中有不少只使用一個兩個頁面的區, DBCC SHRINKFILE的效果就不會明顯。