SQLServer內核架構剖析 (轉載)

SQL Server內核架構剖析 (轉載)

本文原貼出自:http://www.sqlserver.com.cn程序員

 

這篇文章在我電腦裏好長時間了,今天不當心給翻出來了,以爲寫得很不錯,所以貼出來共享。


不得不認可的是,一個優秀的軟件是一步一步腳踏實地積累起來的,衆多優秀的程序員嘔心瀝血,他們已經不是在簡單的寫代碼,而是在創做一門藝術。sql

和前面提到的暴雪公司的發展相比他們有一個相同之處,即:他們只作經典。不能說他們集中的全世界最優秀的程序員,而實際上他們集中的是全世界最好的思想,而且付諸實踐。數據庫

成功不是靠急於求成,而是靠遠見。祝Microsoft SQL Server越走越遠。



咱們作管理軟件的,主要核心就在數據存儲管理上。因此數據庫設計是咱們的重中之重。爲了讓咱們的管理軟件可以穩定、可擴展、性能優秀、可跟蹤排錯、可升級部署、可插件運行,編程

咱們每每研發本身的管理軟件開發平臺。咱們老是但願去學習別人的開發平臺(如用友或金蝶或SAP),但咱們卻老是感嘆管理軟件業務處理細節繁多,安全

而數據庫管理軟件卻簡單的SELECT、INSERT、DELETE、UPDATE四個命令就搞定性能優化

咱們多但願有一天能作出一個架構,也能夠這麼簡單就搞定管理軟件。咱們每每研究別人的架構,卻忘記了咱們身邊咱們最熟悉的數據庫的架構。服務器

因此,今天,我想帶領你們一塊兒剖析一下數據庫的架構,來探索數據庫的架構思想。而我本人呢,只熟悉SQLSERVER這一種數據庫產品,因此我就拿SQLSERVER來分析。網絡


在講SQLSERVER內部原理的以前,我以爲很是有必要向你們介紹一下SQLSERVER的歷史
讓咱們站在1999年,看看計算機數據庫業界到底處於什麼狀態。
1999年,Oracle已經於1998年9月發佈了Oracle 8i(可能中文版在1999年纔來到中國)。架構

Oracle 8i支持用JAVA編寫存儲過程,支持XML,支持Linux。
1999年1月,SQLSERVER7正式發佈。SQLSERVER7重構了整個數據庫引擎(至關於重寫了SQLSERVER)。 併發

SQLSERVER第一次完整性的支持了行鎖(有沒有搞錯,過去人是怎麼使用數據庫產品的。1988年,Oracle6就支持行鎖。另外1988年,Oracle就開始研發ERP產品。誰說Oracle是ERP門外漢,能夠參考這個)。
看看他們倆的前一個版本。若是你入行比較晚(2000年之後),可能對如下文字更感到驚訝。
1992年Oracle7發佈。有了存儲過程、觸發器、引用完整性校驗、分佈式事務處理。(天哪,Oracle7纔有了這些東西)。
1995年,SQLSERVER6發佈。SQLSERVER6是微軟真正意義上的第一個數據庫產品(真是爆料,你們沒想到SQLSERVER6纔是微軟第一個數據庫產品那版本6以前的五、四、三、二、1是怎麼度過的)。

由於1994年,微軟和Sybase掰了(Sybase是第一個運行於PC上的C/S數據庫產品)。微軟爲了進入數據庫產品領域,本身又沒有經驗,

因而和Sybase一塊兒合做(當時微軟是全世界第一大軟件公司,微軟1986年上市。Sybase有產品,缺錢。微軟缺產品,有錢。因而一拍即合)。

直到1994年,微軟也不須要Sybase了(已經學會了數據庫技術),Sybase也感受微軟太狼子野心,因而合做分裂。微軟開始本身作本身的數據庫。


歷史說完。咱們言歸正傳。

不少入門級作管理軟件的,SQL語句玩的熟練,從子查詢到Having到交叉表統計SQL都能作出來,甚至存儲過程能寫2000多行,遊標、自定義函數、觸發器、約束用的眼花繚亂。

再入點門,在SQL查詢器中可使用SQL分析優化索引,用SQL Profile能夠跟蹤SQL,甚至在性能查看器中監測SQLSERVER內存、CPU、線程、I/O的運行狀態,甚至爲本身會使用DBCC而沾沾自喜。


你是如此熟悉SQLSERVER,又是對SQLSERVER如此陌生。
我今天就用架構的角度來給你們分析一下SQLSERVER架構和原理。短短一篇博文確定只能面上的多一些,深一層的可能須要連載數篇文章甚至一塊大磚頭書才能講完整。

不過,我但願個人博文可以拋磚引玉,使你們能從一個過去沒有想過的角度去看SQLSERVER。

 


SQLSERVER,做爲一個數據庫產品,我我的認爲,最重要的就是兩大塊:存儲引擎和查詢引擎(關係引擎)。


其餘的日誌、事務、鎖、索引等等都是圍繞他們來工做的。

 

關係引擎(查詢引擎)上層
SQLSERVER是C/S產品,因此一條SQL語句要讓SQLSERVER執行,必需要傳輸到SQLSERVER服務器端。傳輸,咱們固然知道須要NetBEUI、TCP/IP等等網絡傳輸協議。可是光有這些還不行。

客戶端如何發,服務器端如何收,如何確認發的和收的正確完整,如何確實發的和收的已經結束,如何發和收能跨越各類網絡協議(如UNIX和WINDOWS和NOVELL通信),如何保證數據安全校驗,

如何保證數據收發是同步仍是異步,就須要在網絡傳輸協議之上再構造一層協議。SQLSERVER既支持IPC機制(interior process call),也支持RPC機制(remote process call)。你想一想你的管理軟件開發平臺是否有這一層。

固然,如今的消息服務器已經專業的提供了這一機理,可靠的、安全的、高效的、異步的、消息壓縮、消息拆分、智能路由、集羣,跨越不一樣的操做系統、不一樣的編程語言、不一樣的通信協議、不一樣的硬件平臺的消息數據傳輸。

 

可能你過去不了解消息中間件,經過這一案例能夠知道消息中間件的用途。


SQL語句被可靠無誤的發送到了服務器端,SQLSERVER引擎中第一個模塊就來接待這個SQL數據。這個模塊的名字叫:Open Data Services

它監聽新的鏈接;清除失敗鏈接;將結果集、消息和狀態返回給客戶端。

 


SQLSERVER客戶端和服務器端之間傳輸數據,數據包是有格式的。在SQLSERVER中被稱爲tabular data stream

這個數據流是令牌控制客戶端和服務器端對話(不然,客戶端說了N句話,服務器端返回N句話,沒有令牌就混在一塊兒了,不知道哪一個回答是對應哪一個請求的)。

咱們每每不能直接和Open Data Services打交道,把數據放進來。而是咱們必須經過ODBC、ADO或DB-Library來發送tabular data stream。

 

而SQLSERVER返回的數據結果,也是經過這些ODBC之類發回tabular data stream。你看看SQLSERVER設計的多巧妙,一個通用數據訪問接口屏蔽了你和SQLSERVER之間直接溝通

就如同WINDOWS API屏蔽了內核讓你沒法訪問,就如同DirectX屏蔽了UI和外設的操控。

 


SQL語句-ODBC-編碼成tabular data stream-IPC或RPC-網絡協議-IPC或RPC-解碼tabular data stream-ODBC-Open Data Services。
Open Data Services監測客戶端鏈接。若是併發太多,它會建立鏈接,若是服務完,它會本身維護鏈接納入池中。在池中保留一段生命期,它會本身釋放鏈接

若是有的客戶端鏈接中途忽然斷掉(如客戶端重啓了),它在偵聽後無迴應發送keepalive數據包偵測是否死掉,它也會本身整理本身的鏈接的。

咱們在SQLSERVER線程中看到的鏈接,就是Open Data Services建立的。

 


Open Data Services有了鏈接(多是建立的多是從池裏拿出來的,池化、建立、銷燬都是很是講究技能的

池化多少,上下文資源如何保留,池化多長時間,何時該銷燬,調度不當就會嚴重消耗資源),就把SQL hang住。這時,是接到了Open Data Services的讀緩衝區裏面。

這個緩衝區爲高性能處理數據的SQLSERVER帶來一絲喘息機會,而就這一絲喘息機會,讓SQLSERVER能夠遊刃有餘(你的設計有嗎?)。

而Open Data Services有一個寫緩衝區。SQLSERVER把檢索到的數據,檢索出來就當即放進寫緩衝區,寫緩衝區一滿就當即被Open Data Service發走。

當我過去研究SQLSERVER原理的時候,我經常讚歎,一個小小的SQLSERVER外圍模塊都設計如此精妙,實在讓人佩服。咱們常常在追求海量數據存儲和Cache架構,咱們卻無視咱們手邊的SQLSERVER。


SQL語句放到讀緩衝區,SQLSERVER的查詢引擎(關係引擎)就開始工做了。它老是在偵聽這個讀緩衝區
SQL語句遇到的關係引擎的第一個模塊就是命令分析器。咱們在SQL查詢分析器中看到的查詢分析結果就是它的輸出傑做。它來構造查詢樹。

首先是將你的SQL語句規範化(你想一想你寫的軟件代碼,輸入數據來了什麼都無論就直接處理,連輸入數據校驗都沒有,怎能穩定),不然之後的步驟將很差操做,若是你的SQL語句有語法錯誤,

這個查詢樹的構造就沒法完成,因而中斷。而要規範一個SQL語句,首先要從SQL語法庫中抽取SQLSERVER現有支持的各類語法和函數,SELECT * 平展 ,字段訪問權限校驗
一旦構形成功,關係引擎的第二個模塊就是命令優化器,來裁剪這棵樹。一個SQL語句能夠生成多種執行和優化的方案(若是你使用過那種SQL優化工具的話,你就能理解),

SQLSERVER會選擇最節省內存、CPU利用率、I/O次數(I/O是性能優化最要命的地方,每每性能就瓶頸在I/O上)的那一種方案。

優化器會根據每張表的數據統計/統計信息(有時候你爲了性能優化,必須定時期同步更新一下統計,不然優化就會有偏差)。

並且優化器也會根據查詢樹去選擇合適的索引(若是使用索引代價大,它會自動選擇全表掃描),優化器也會根據查詢樹知道先取哪些表的數據,

而後再內存中如何合併數據,以獲得你想要的結果(有時候想一想優化器真偉大,你一個SQL過去,它須要在極短的時間內作多少事啊,爲了能在極短期內肯定一個相對優化的方案,它也不可能窮舉全部可能的方案,因此咱們作海量數據優化的時候,每每評估多種方案,而後修改本身的SQL語句以符合產生最優的方案)。

 

規範化、優化完SQL語句,就要產生執行計劃了。SQL管理器負責執行計劃的產生。由於你發過來的SQL語句多是一個SELECT,也多是一個INSERT或UPDATE。即便SELECT,

也面臨着用戶權限的限制(你若是設置過某一個SQLSERVER用戶的對象權限和列權限,你就會明白)。而INSERT之類更新語句,又會涉及到權限、默認值、約束、表達式、主外鍵、觸發器

一個優化完的SQL,具體要真正讓SQLSERVER從內存或硬盤上把數據找出來或者更新回去,須要不少細節的步驟。
查詢執行器來負責SQL的執行。由於SQL的執行要涉及到事務、鎖、等待、CPU調度,內存頁失效影響、I/O存取影響,因此查詢執行器會協調不少其餘模塊,但各個模塊來負責處理,

而查詢執行器並不真正所有包辦,不然讓事務管理器、鎖管理器、索引管理器、頁面文件管理器、緩衝管理器、行管理器、日誌管理器幹嘛去。

查詢執行器是查詢引擎的最後一個模塊,接下來的模塊都屬於存儲引擎的範疇。因此,從上看,查詢引擎最主要是構造SQL查詢樹、優化裁剪SQL查詢樹,根據查詢樹產生執行計劃,而後協調執行查詢樹,

把結果返回去。


存儲引擎  下層

而真正要把數據取出來或存進去,就須要存儲引擎來工做了。
首先根據執行計劃,要存取哪些數據頁和索引頁。這就是訪問方法管理器(access methods manager)要作的事情。但其實真要打開這些頁,還不是訪問方法管理器本身要親手乾的。
親手幹這個活的是一個叫「緩衝區管理器」的模塊。由於在硬盤上的數據是不可能計算處理的,必需要在內存中才能讓CPU來計算。因此要存取那些數據頁和索引頁,就通知讓緩衝區管理器來作。

若是數據沒有在內存中,就讓緩衝區管理器來讀入,若是數據已經在內存中了,緩衝區管理器只有返回便可。這個過程是被緩衝區管理器來屏蔽的,對於訪問方法管理器是透明的

你們可不要覺得訪問方法管理器啥事不作,只是一個發佈調度命令的。這可錯怪了它。由於SQLSERVER要保證高速處理,必須預先預測好哪些數據頁和索引頁要處理。

不能人家緩衝管理器已經處理完,你訪問方法管理器才計算下一步將要處理的頁面。要知道,這些管理器但是不分哪一個用戶來處理的。若是接受來自100多個併發的用戶,發來各類各樣的數據處理請求,

你怎麼能預測到哪些數據頁和索引頁要處理呢?這就須要一個統一的調度。並且這個統一的調度也影響着緩衝區管理器。你不能請求一個大數據,緩衝區管理器這才火燒屁股才擴大緩衝區,而後裝載數據,

那樣流水線就停下了。緩衝區管理器必須預先知道將在不久要有一個大數據,因此在並行運算的時候就有獨立線程來擴展了緩衝區。由於擴大緩衝區還和操做系統有關。

你要擴大緩衝區,正好遇到WINDOWS頁面失效(缺頁中斷 page fault),就涉及到你的虛擬文件的變化。而頁面失效又會影響CPU和I/O。因此頁面失效是一個性能影響很大的問題。

而提升命中率是咱們性能優化一直努力的重點。若是數據長時間不用,緩衝區管理器就要讓這塊內存數據過時,能夠被新的數據覆蓋。不然緩衝區老加載不卸載也不行。

再說,有些數據已經被更新了,你數據老化了,不從新讀入,你的數據就引發讀錯誤了。


咱們知道,數據頁包含數據行。索引頁包含索引行。數據行就由行管理器來控制。而索引行,由索引管理器來負責。
而單行上的檢索、修改、執行,又被事務管理器鎖管理器影響着。事務,有顯性事務和隱性事務兩種。而鎖,又有共享鎖、排它鎖、更新鎖、意向鎖。而鎖,還分爲行鎖、頁鎖、表鎖、數據庫鎖。

而鎖,又有死鎖的可能性。鎖的不一樣,加上事務的影響,這個行是否能讀、能修改,能怎樣的讀(讀一致仍是髒讀),是等待事務和鎖,仍是能夠進行,就受了不少影響。

由於一張數據頁上放的行是有限的,尤爲還有填充度的影響(如填充度爲80%,就這個數據頁面只能填充80%就必須分頁,以防之後有數據插入的時候,就很是影響數據插頁,

這也是性能影響比較大,尤爲在插入數據比較多的狀況下)。SQLSERVER的一張數據頁默認是8K,除去填充度和數據頭,也沒有多少可存儲的數據了。

這就是爲了關係型數據庫都勸阻你們要小表大數據。也就是說,列要少,列要短,頻繁訪問的列要在前。數據能夠海量。若是行長了,你想要檢索和更新多少數據頁,這須要多少頁面調度,

面臨着頁面失效和鎖機制的影響。並且,大文本和可變行,都是指針存儲,須要跳轉查找,更浪費了很多時間
而索引管理器,最主要在維護着索引B樹。沒有索引頁,咱們就要作全表掃描了,那須要載入多少數據頁,並且還要逐行掃描,若是趕上事務和更新鎖,就更有問題。

因此,索引是很是重要的。而一個表,能夠創建不少索引。索引,能直接找到所須要的行,而無須全表掃描。可是,你的索引若是僅僅是男女,或者你的索引涉及到可變行,都對索引不利。

索引,不宜創建多。不然維護索引頁的成本和消耗也很是多。索引頁更要涉及到插頁、拆頁,頻繁改動涉及到索引的字段,會讓索引頁劇烈變更,尤爲數據量越大影響越大。

我就不在這裏講解如何利用索引優化SQL了,不然一本書也講不完。


數據不斷存取,數據不斷被維護,載入內存或從內存中寫入硬盤。其實都是惰性寫入器在照顧。惰性寫入器來按期掃描老化數據,讓硬盤和內存中的數據是一致的。

有這個惰性寫入器,就有了內存和硬盤的差別時間窗。就有可能出現異常。一旦服務器忽然斷電,沒有來得及寫會磁盤的怎麼辦。也也涉及到另外一個模塊:日誌管理器

日誌管理器利用檢查點的機制維護着日誌文件。在服務器從新啓動的時候,重寫載入日誌來把數據恢復到一致性。寫日誌,固然要比寫數據要容易的多,快的多。

由於寫數據要操控內存和硬盤,還要注意權限、鎖、事務,因此忽然斷電,你還沒反應就來不及了。因此日誌這種輕量級的方法,

就能夠在恢復一致性上有很好的幫助(固然,也丟失數據。日誌頁也沒來得及寫入硬盤)。

 


講到這裏,就剩下事務管理器、鎖管理器。這兩個管理器和顯性事務、隱性事務、顯性鎖、隱性鎖、事務隔離級別、鎖級別、行管理器、索引管理器都有不少關係。

 

 

微軟有WINDOWS優點,又有Jim Gray這樣的巨師坐鎮(Jim Gray是圖靈獎得到者,就是此爺提出了數據庫事務這一律念。蓋茨爲了讓此爺爲微軟工做,而此爺不喜歡雷德蒙每天下雨的天氣,

因而在加州陽光中給此爺單獨建了一座研究院  微軟加州研究院)。

百度百科:http://baike.baidu.com/link?url=n0vbmC2FrrVB2xWyHFlQqntBeG9yOvX1zqrHYM6J9R0-xFAkjbnTuSh6Vh94c_m2yQ8nRdZAqD3V9llgVLVwxa

 

 

因此,在性能上,我我的認爲SQLSERVER的性能是很是優秀的(你想一想,一個數據庫產品的性能受什麼方面的影響)。

至於業界老稱SQLSERVER沒法管理海量數據,性能不佳,我我的感受都是業界在以訛傳訛而尤爲中國內地IT業界,大部分都是入門級在跟帖嘈雜,尤爲還有一批更不懂技術的媒體記者或寫手


若是真要去說SQLSERVER不行,大型海量數據管理必須用某某數據庫產品,我建議從內部原理、內部架構、內部實現三個層次諸多方面來剖析到底在不在理。


最後就是I/O管理器了。我一直不認同SQLSERVER內核中有I/O管理器。由於SQLSERVER使用的是和WINDOWS一樣的頁面調度和頁面分配方法。

何須要本身另創一套呢。就如同SQLSERVER把頁面、硬盤、內存、線程、CPU交給了WINDOWS同樣。

SQLSERVER做爲WINDOWS上的一個應用軟件,應該和WINDOWS上的其餘軟件同樣被WINDOWS管理。SQLSERVER又不跨平臺,無須本身管理。
除了SQLSERVER這些內核涉及精妙之外,SQLSERVER的外圍工具也設計的至關好。

如SQLSERVER的用戶安全性管理方法、對象分類(表、列、約束、默認、索引、觸發器、存儲過程、視圖、主鍵)、對象權限方法、元數據自管理方法、SQL語言、SQL查詢分析器、SQL跟蹤器、SQL性能分析器、SQL數據庫(master\msdb\tempdb\model)。


想想,你的管理軟件平臺有這些架構思想嗎?

http://blog.csdn.net/hzbooks/article/details/2247912

數據庫界的超級牛人、1998年圖靈獎得到才者Jim Gray先生於2007年1月28日早上獨自乘船離開San Francisco Bay,去一個叫Farallon小島灑他母親的骨灰,不幸在外海失蹤。直到如今也沒有他的任何消息,美國海岸警衛隊已經展開了大範圍的搜索。 
 
計算機科學界的諾貝爾獎--圖靈獎的評獎極爲嚴格,不多在同一領域授予兩人。所以圖靈獎得主不只是做出了卓越貢獻的超級科學家,也被公認爲本研究領域的領袖。 做爲計算機的傳統主流方向,數據庫只有三位圖靈獎得主,都是大名鼎鼎的人物,開創了屬於本身的時代。三巨頭之一的E.F.Codd於2003年逝世,數據庫之父Bachman也早已退休,離開了學術界,目前本研究領域碩果僅存的則只有Jim Gray一位:
 
Charles W. Bachman (1973) -- 數據庫
Edgar Frank Codd (1981) -- 關係數據模型
Jim Gray(1998) -- 數據庫和事務處理
 
數據庫的教科書通常單獨開一到兩章來說解事務及其重要性,事務是數據庫應用於銀行,金融等行業的基礎。信用卡刷卡,網上轉帳這些操做都是做爲數據庫事務來完成的,事務機制保證了這些操做的正確性和完整性,從而獲得普遍的應用。而提出事務概念和相關技術的,正是Jim Gray。此外,他仍是聯機分析處理技術( OLAP)的奠定人,他提出了 Data Cube等重要概念。近十年來(並且可能一直延續到將來十年),
他一直是 數據庫數據倉庫數據挖掘等領域當之無愧的領軍人物。
 
官方已經宣佈Jim Gray 先生死亡。還會有奇蹟出現嗎?
 

2015-4-13 補充
事務管理 包含兩個組件:一、鎖管理器  二、事務日誌管理器

Well I don't know whether writer wrote about Log manger or not but I would try to explain you

Storage engine of SQL Server has component called as Transaction Manager which manages locks for transaction an also manages transaction logs.

This Transaction manager has two components

1. Lock Manager

2. Log Manager

相關文章
相關標籤/搜索