--------------------------------------------------------------------------------------算法
原文轉自:http://qianzhang.blog.51cto.com/317608/1217346數據庫
--------------------------------------------------------------------------------------緩存
1、引言服務器
在SQL Server數據庫中,數據是如何被讀寫的?日誌裏都有些什麼?和數據頁之間是什麼關係?數據頁又是如何存放數據的?索引又是用來幹嗎的?工具
一塊兒看看SQL Server的存儲引擎。操作系統
2、SQL Server的存儲引擎3d
大體分爲如下幾部分:日誌
1. 數據庫如何讀寫數據blog
2. 內存索引
3. 日誌
4. 數據
5. 索引的結構和分類
6.索引的遍歷和維護
下面一 一詳細介紹:
1. 數據庫如何讀寫數據
1.1. 數據讀寫流程簡要
SQL Server做爲一個關係型的數據庫,天然也維持了事務的ACID特性,數據庫的讀寫衝突由事務的隔離級別控制。不管有沒有顯式開啓事務,事務都是存在的。
(1)事務開始
(1.1)全部DML語句必然是基於事務的,若是沒有顯式開啓事務(即手動寫下begin tran),則事務處理的最小單位是每一條DML語句,並自動提交事務。
(1.2)若是手動開啓一個事務(begin tran),或開啓隱式事務(set implicit_transactions on),才須要手動提交事務(commit tran),不然SQL Server自動提交事務。
(2)發起DML
(2.1)DML語句包括:insert、delete、update;
(2.2)DDL語句最終是被轉化爲對系統表的DML,在SQL SERVER中DDL語句也能夠被回滾,好比:CREATE/ALTER/DROP/TRUNCATE,在ORACLE裏是不能夠的,另外SQL Server中的DCL語句:DENY,REVOKE,也能夠被回滾;
(3)數據是否在內存
(3.1)在內存中使用hash算法查找數據,若是找到記爲邏輯讀;
(3.2)若是數據頁不在內存中,則須要從磁盤上的數據文件中,讀取相應的數據頁到內存中,即物理讀,物理讀也會被記數爲邏輯讀,也就是說不管內存中有沒有數據,邏輯讀是必定有的。
(4)修改數據
(4.1)在SQL Server內存的數據緩衝區中將數據頁修改,此時數據頁稱爲髒頁(Dirty Page);
(4.2)在SQL Server內存的日誌緩衝區中記錄REDO LOG,暫稱爲髒日誌;
(5)事務結束
(5.1)提交(COMMIT),此時將當前事務的髒日誌刷新到數據庫的日誌文件中,並打上事務結束標記(COMMIT),髒頁有可能暫未被刷新到數據文件中;
事務日誌結構以下(可經過log explorer等工具查看)
BEGIN TRAN
DML
COMMIT TRAN
(5.2)回滾(ROLLBACK),此時讀REDO LOG獲得反向DML操做,反向修改髒頁,正向DML 與 反向DML都會被記錄在數據庫的日誌文件中,並打上事務結束標記(ROLLBACK),一樣,髒頁有可能暫未被刷新到數據文件;
事務日誌結構以下:
BEGIN TRAN
DML
反向DML
ROLLBACK TRAN
不難發現,SQL SERVER的日誌容易成爲一個瓶頸,由於在寫的同時引入了讀,即引入了競爭,而ORACLE用UNDO SEGMENT很好地避免了這個問題,REDO LOG永遠只是在被串行寫。
(6)刷新數據頁
(6.1)SQL Server數據庫遵循預寫日誌(WAL:Write-Ahead Logging)原則,由於關係型數據庫是基於事務的,而日誌正是事務ACID特性的保證,也是數據恢復的保證。
(6.2)檢查點(Checkpoint),檢查點週期性的將髒頁刷新到數據庫的數據文件中,最終在日誌文件上打上檢查點標記(Checkpoint),至此上面事務中修改的數據被正式寫入 到磁盤上的數據文件中。
-------------------------------------------------------------------------------------------------------------------------------
1.2 數據讀寫流程深刻
試想:
(1) 日誌是否是必定要在COMMIT後才寫到日誌文件?若是有個很長很大的事務,那麼提交日誌時,日誌從緩衝區被寫入磁盤,豈不是要等好久?
(2) 數據是否是必定要在日誌提交後,發生了CHECKPOINT,才寫到數據文件?若是日誌一直沒提交,那麼數據緩衝區豈不是很擁擠?
考慮到這2點,SQL Server還會經過Log Writer/Lazy Writer不定時的刷新日誌/數據到磁盤,至於日誌和數據的一致性,在啓動或者數據庫還原時,SQL Server會去作檢查,也便是咱們常說的前滾(REDO)和回滾(UNDO)。
(1)SQL SERVER MEMORY
(1.1) SQL SERVER 佔用服務器內存的一部分,非SQL SERVER 佔用的內存,供操做系統及服務器上的其餘應用程序使用;
(1.2) SQL SERVER 內存結構可分爲兩大塊,關於內存結構參見下面說的內存部分,圖中僅標出Buffer Pool中的數據及日誌緩存;
(2) 事務結束
(2.1)事務結束的前提是日誌緩存成功寫入到日誌文件中,此時,數據庫纔會返回事務結束的響應。也就是說客戶端收到COMMIT/ROLLBACK語句運行成功的消息時,日誌已被成功寫入日誌文件(數據還不定是否被寫入數據文件);
(2.2)日誌緩存並非必定要等到事務結束時才刷新到日誌文件的。
(3) LOG WRITER
(3.1)當遇到長事務時,沒必要等到發出事務結束命令,LOG WRITER也會週期性地將髒日誌刷新到日誌文件,以保證用戶發出COMMIt時快速響應並結束;
(3.2)微軟公司並無公佈SQL SERVER除去COMMIT外,LOG WRITER將髒日誌刷新到日誌文件的週期,這裏能夠參考ORACLE的,每3秒;或者日誌緩衝區1/3滿;或者包含1M的髒日誌。
(4) LAZY WRITER
(4.1)LAZY WRITER週期性掃描緩存(默認1s),維護自由頁面列表(free page),根據LRU算法將已刷新到磁盤的頁釋放;
(4.2)若是是髒頁則刷新到磁盤(這時事務可能還未提交),一樣也是先將日誌刷新到日誌文件中,而後再將髒頁刷新到數據文件中,最終內存頁釋放並加入自由頁面列表;
(5)CHECKPOINT
(5.1)CHECKPOINT同LAZY WRITER同樣也會刷新髒頁到數據文件中(只刷新已提交的事務數據),但不會維護內存自由頁面列表;
(5.2)能夠設置SP_CONFIGURE ‘RECOVERY INTERVAL’選項來改變CHECKPOINT發生的頻率,默認爲1分鐘一次。
小結:能夠發現,數據和日誌被寫入數據/日誌文件,並非同步的。有可能寫入/提交了日誌,數據沒有寫入磁盤;有可能寫入了數據,事務未被提交;
(1) 針對有完整事務日誌,數據未被寫入磁盤的狀況,啓動/還原數據庫時,SQL SERVER作前滾(REDO);
(2) 針對有數據寫入數據文件,日誌未完整提交的事務,啓動/還原數據庫時,SQL SERVER作回滾(UNDO)。
-------------------------------------------------------------------------------------------------------------------------