當truncate table發生時,如何進行恢復,相信大部分人都會選擇經過還原備份到truncate table前,而後將數據從新導入正式表中。sql
那麼在SQL Server中是否是真的只有這種方法呢,固然不是,這也是本文即將介紹的內容,前提條件是SQL Server完整恢復模式(大容量日誌模式未作測試,暫不介紹)。數據庫
首先,瞭解一下truncate table的一些相關知識ide
官檔:
測試
TRUNCATE TABLE 經過釋放用於存儲表數據的數據頁刪除數據,且僅在事務日誌中記錄頁釋放。日誌
這句話包含的信息量是很大的,經過實驗進行驗證,解釋以下:
orm
truncate table時,數據庫日誌中不會記錄確切的已刪除值,只記錄截斷記錄的頁的ID,而且這些記錄所佔用的空間會被標識爲可重寫,blog
mdf中會暫時保留這些頁內的數據,當有新事務寫入這些頁時,truncate table的數據將會被覆蓋(數據頁被format,而後從新使用)。事務
測試:
hash
建立一張表,並插入數據it
create table test_truncate(id int,name varchar(20),address varchar(20)) go insert into test_truncate select 1,'zhangsan','first road' go insert into test_truncate select 2,'wangxiao','second road' go
利用dbcc ind找到該表的數據頁,以下PageType=1爲數據頁,即爲:288
使用dbcc page查看數據頁內容
PAGE: (1:288) BUFFER: BUF @0x000000000563C600 bpage = 0x0000000150020000 bhash = 0x0000000000000000 bpageno = (1:288) bdbid = 9 breferences = 0 bcputicks = 0 bsampleCount = 0 bUse1 = 56673 bstat = 0x10b blog = 0x7adb21cc bnext = 0x0000000000000000 PAGE HEADER: Page @0x0000000150020000 m_pageId = (1:288) m_headerVersion = 1 m_type = 1 m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8000 m_objId (AllocUnitId.idObj) = 489 m_indexId (AllocUnitId.idInd) = 256 Metadata: AllocUnitId = 72057594069975040 Metadata: PartitionId = 72057594062241792 Metadata: IndexId = 0 Metadata: ObjectId = 935674381 m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 8 m_slotCnt = 2 m_freeCnt = 8021 m_freeData = 167 m_reservedCnt = 0 m_lsn = (49:7380:2) m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 0 DB Frag ID = 1 Allocation Status GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED Slot 0 Offset 0x60 Length 35 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 35 Memory Dump @0x000000006DDF8060 0000000000000000: 30000800 01000000 03000002 00190023 007a6861 0..............#.zha 0000000000000014: 6e677361 6e666972 73742072 6f6164 ngsanfirst road Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4 id = 1 Slot 0 Column 2 Offset 0x11 Length 8 Length (physical) 8 name = zhangsan Slot 0 Column 3 Offset 0x19 Length 10 Length (physical) 10 address = first road Slot 1 Offset 0x83 Length 36 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 36 Memory Dump @0x000000006DDF8083 0000000000000000: 30000800 02000000 03000002 00190024 0077616e 0..............$.wan 0000000000000014: 67786961 6f736563 6f6e6420 726f6164 gxiaosecond road Slot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4 id = 2 Slot 1 Column 2 Offset 0x11 Length 8 Length (physical) 8 name = wangxiao Slot 1 Column 3 Offset 0x19 Length 11 Length (physical) 11 address = second road DBCC execution completed. If DBCC printed error messages, contact your system administrator.
能夠看到數據頁中存在的記錄
Slot 0 Column 1 Offset 0x4 Length 4 Length (physical) 4 id = 1 Slot 0 Column 2 Offset 0x11 Length 8 Length (physical) 8 name = zhangsan Slot 0 Column 3 Offset 0x19 Length 10 Length (physical) 10 address = first road Slot 1 Column 1 Offset 0x4 Length 4 Length (physical) 4 id = 2 Slot 1 Column 2 Offset 0x11 Length 8 Length (physical) 8 name = wangxiao Slot 1 Column 3 Offset 0x19 Length 11 Length (physical) 11 address = second road
執行truncate table後
能夠看到數據頁中仍保留着truncate table的相關記錄。
那麼,truncate table的第二種恢復方法就顯而易見了,在這些數據被覆蓋以前,從頁面中將數據提取出來,並恢復到表中。