SQL Server日誌解析
1、事務解析
SQL Server 使用Write-ahead logging (WAL)方式保證任何資料變更的日誌要比資料變更先發生。在完全恢復模式下,對資料庫中任何物件的變更操作都會被記錄在日誌中。注意是所有的資料物件,包括:tables, views, stored procedures, users, permissions等。
使用fn_dblog()查詢日誌記錄:
USE TestDB1
GO
SELECT * FROM [sys].[fn_dblog](NULL,NULL)
插入一條語句的日誌記錄如下:
LOP_BEGIN_XACT:標記一個事務的開始,也是日誌中唯一包含事務開始時間的記錄,同時還包含發出語句使用者的SID
LOP_COMMIT_XACT:標記一個事務的結束
LOP_LOCK_XACT:鎖
LOP_INSERT_ROWS、LOP_DELETE_ROWS、LOP_DELETE_ROWS:記錄實際的資料修改資訊
2、fn_dblog()欄位解析
Current LSN:當前LSN
事務日誌中的每一條日誌記錄由LSN(Log Sequence Number)唯一標識。LSN是有序的,如果LSN2大於LSN1,則LSN2的日誌所代表的資料修改操作發生在LSN1之後。
Operation:當前LSN所做的操作
Context:操作的上下文
Transactoin ID:事務ID號
Log Record Fixed Length:LSN記錄的所佔虛擬日誌檔案的固定長度
Previous LSN:前一個LSN號
AllocUnitID:修改的那條資料所屬分配單元ID
AllocUnitName:修改了資料的表名
Page ID:資料所在頁面(16進位制)
檢視page id為289頁的記錄: DBCC Page ({dbid|db name}, file num, page num, [print opt])
Slot ID:資料所在資料頁面的第幾條記錄
Partition ID:資料所在資料頁面的所在分割槽ID
資料修改操作(如LOP_INSERT_ROWS)總是會記錄它操作的物理內容(PageID,SlotID)和物件:分配單元(Allocation Unit ID)和分割槽ID(Partition ID)。
檢視AllocUnitName列是確定哪一個物件被修改的最簡單的方式。
Page ID 和Slot ID告訴我們哪個頁的哪一個槽位被事務修改了。
可以通過DBCC PAGE來檢視頁內容。
Checkpoint Begin:Checkpoint開始時間
Checkpoint Begin DB Version:當前資料庫版本 SQL2005是611 SQL2012是706
Checkpoint End:checkpoint的結束時間,這個時間肯定在Checkpoint Begin的下一條事務日誌記錄的位置
Minimum LSN: 這個第一個日誌記錄的日誌序列號 (LSN),稱為最小恢復 LSN (MinLSN)
Dirty Pages:髒的資料頁
Oldest Replicated Begin LSN:如果資料庫配置複製的話,那麼最老的複製起始LSN
Next Replicated End LSN:下一個複製結尾LSN
Last Distributed End LSN:最新的分發結尾LSN
SPID:執行當前操作的程序ID
Beginlog Status:開始記錄事務日誌的狀態,這個狀態表示現時能夠正常記錄事務日誌
Begin Time:事務開始時間
Transaction Name:事務名稱
事務名稱分類:
(1)顯式提交-命名事務:[事務名]
begin transaction tran_test
use TestDB1
insert into test values(1,0)
commit
(2)顯式提交-未命名事務:user_transaction
begin transaction
use TestDB1
insert into test values(0,0)
commit
(3)隱式提交-DML:INSERT、UPDATE、DELETE
use TestDB1
insert into test values(0,0)
(4)隱式提交-DDL:CREATE TABLE、ALTER TABLE、DROPOBJ
useTestDB1
create table test(
a int,
b int,
primary key(a),
)
SplitPage:頁拆分
可以根據Parent Transaction ID獲取執行頁拆分的事務,頁拆分是B-TREE根據排序鍵維護資料順序的一種方式,CREATE TABLE插入元資料會導致內部元資料表的頁拆分,
Allocate Root:頁分配
正常情況,建立表時,不會分配頁給它。第一個INSERT會觸發分配第一個頁給表。分配操作由單獨的事務完成,並且會立即提交。即使觸發頁分配的那個INSERT事務被回滾或者延遲提交,也不會影響其它的資料插入操作。從這裡也可以看出,一個會話中,可以開始和提交獨立於會話主事務之外的事務的,只是這個功能沒有提供給T-SQL,只是內部使用。
Transaction SID:啟動事務的登入名的SID,可以用SUSER_SNAME()函式獲取到實際的登入名。
End Time:事務結束時間
Transaction Begin:記錄這個事務的begin transaction的時候的cureent LSN
Master DBID:顯示當前master資料庫的DBID
Preplog Begin LSN:啟動資料庫前的前一個事務日誌LSN
Prepare Time:準備啟動資料庫的時間
New Split Page:哪個資料頁產生了頁拆分
Rows Deleted:資料頁有多少行被刪除了
Description:描述這個事務是幹什麼的,有時候事務名稱不一定就是他所做的操作名稱,需要通過Description指示
Lock Information:
Lock Information列的完整內容:
其中有表的Object ID,頁ID和索引鍵的鍵鎖資訊。
對於B-TREE,鍵鎖就是鍵值的HASH值,所以通過它能定位到資料行(就算髮生頁拆分,但是鍵值是不會變的)。
通過鍵鎖資訊,我們正確定位到第一個INSERT的行。
注意,HASH值存在HASH碰撞的可能,即不同的鍵值生成了同樣的HASH值。碰撞的概率是非常低的,如果發生, 上面的查詢會返回多行。
Offset in Row:
RowLog Contents 0:
RowLog Contents 1:
RowLog Contents 2:
RowLog Contents 3:
Log Record:
3、Operation與Context
Operation:當前LSN所做的操作
Context:操作的上下文
Operation |
Context |
解釋 |
LOP_SET_BITS |
LCX_DIFF_MAP |
設定點陣圖,資料: 差異(Differential)備份:只備份上次完整備份後,做修改的部分。備份單位是區(Extent)。意味著某個區內即使只有一頁做了變動,則在差異備份裡會被體現.差異備份依靠一個BitMap進行維護,一個Bit對應一個區,自上次完整備份後,被修改的區會被置為1,而BitMap中被置為1對應的區會被差異備份所備份。而到下一次完整備份後,BitMap中所有的Bit都會被重置為0 而這個BitMap在資料庫第7頁: DCM頁 差異變更(Differential Changed Map,DCM)頁面他跟蹤一個檔案中的哪一個區在最新一次完整資料庫備份之後被修改過。SQLSERVER用在增量備份時只對已發生資料變更的分割槽進行增量備份即可 |
LOP_BEGIN_XACT |
事務開始 |
|
LOP_MODIFY_ROW |
LCX_HEAP |
修改堆表中的某一行記錄 |
LOP_PREP_XACT |
準備啟動資料庫 |
|
LOP_COMMIT_XACT |
提交事務 |
|
LOP_MODIFY_ROW |
LCX_BOOT_PAGE |
修改資料庫啟動頁 |
LOP_MODIFY_HEADER |
LCX_PFS |
修改PFS頁的頁頭部資訊 |
LOP_INSERT_ROWS |
LCX_CLUSTERED |
插入資料到聚集索引的索引頁 |
LOP_INSERT_ROWS |
LCX_INDEX_LEAF |
插入資料到索引的葉子節點即資料頁 |
LOP_FORMAT_PAGE |
LCX_CLUSTERED |
重新組織聚集索引 |
LOP_DELETE_SPLIT |
LCX_CLUSTERED |
刪除聚集索引表的一行記錄引起頁拆分 |
LOP_MODIFY_HEADER |
LCX_HEAP |
修改堆表的某頁的頁頭資訊 |
LOP_BEGIN_CKPT |
LCX_NULL |
檢查點開始 |
LOP_END_CKPT |
LCX_NULL |
檢查點結束 |
LOP_SET_FREE_SPACE |
LCX_PFS |
修改PFS頁設定那個資料頁是空閒的 |
LOP_ROOT_CHANGE |
LCX_CLUSTERED |
聚集索引的根節點改變 |
LOP_INSERT_ROWS |
LCX_HEAP |
插入資料到堆表 |
LOP_FORMAT_PAGE |
LCX_HEAP |
格式化堆裡的資料頁 |
LOP_LOCK_XACT |
HoBt 0:ACQUIRE_LOCK_SCH_M METADATA: database_id = 14 STATS(object_id = 7, stats_id = 11) |
在事務裡獲取鎖 |