1、進程管理web
企業級數據庫服務器可能擁有數千個併發訪問數據庫的用戶。某些用戶可能執行只需較少處理能力的簡單事務,而其餘用戶則可能執行涉及更多系統資源的復瑣事務。 數據庫性能經常基於諸如每小時的事務數或 X個併發鏈接下的最小響應時間等度量來討論。這些性能約束由企業施加,以便確保客戶的質量保證等級。因爲對併發處理具備如此高的需求,企業級數據庫服務器須要運行於大型 SMP服務器上。早期的 Linux內核並不很適合充當須要高併發度的數據庫服務器。這些內核並無隨着系統上的處理器數量的增長而提供良好的擴展性,由於早期內核的開發由單處理器機器所驅動。遷移至多處理器平臺時須要許多全局內核鎖的支持,不然會致使串行化問題。 其中最大的鎖是用於保護單個未排序的運行隊列的自旋鎖(spin lock)。 在單處理器環境中, 單個隊列足以調度全部可運行任務。然而, 在 SMP環境中, 單個運行隊列並不夠,這會成爲一個瓶頸。隨着處理器數量的增多,在運行隊列上鎖競爭的可能性也增長。另
外,因爲該隊列是未排序的,當鎖被持有時調度器須要檢查隊列中的全部任務以便肯定每一個任務的良好度(每一個任務被賦予一個良好度取值, 用於肯定哪一個任務將是被調度至處理器上運行的最佳候選)。 這增長了鎖持有時間, 從而增長了鎖競爭的可能性或加重當前的競爭條件。在 Linux 2.5內核中, 這個惟一運行隊列被刪除並替換爲基於 CPU的運行隊列。擁有多個運行隊列刪除了對單個全局鎖的需求並改進了總體的可擴展性。另外,每一個運行隊列都維護一個優先級列表,有助於調度器選擇要運行的最佳任務。這種優先排序能夠減小隊列上的鎖持有時間,並進一步減小了鎖競爭 。
數據庫
2、內存管理緩存
管理大型企業的數據庫須要在大型對稱多處理(SymmetricalMultiprocessing,SMP)服務器上運行。這種服務器經常配置了海量物理內存。系統的大部份內存都被分配給數據庫緩衝區 cache區域(稱爲數據庫緩衝區)。數據庫緩衝區用於緩存從磁盤讀至內存中的表和索引數據頁。因爲磁盤訪問相對於內存訪問來講是緩慢的操做,將更多內存分配給數據庫緩衝區能夠極大改進數據庫性能。適當調優的數據庫會佔用大部分可用內存,而爲其餘正在運行的應用和操做系統只保留夠用的內存大小。爲數據庫分配過多內存會剝奪其餘應用可用的內存空間。 另外, 過分分配內存會致使過多的交換, 這對於數據庫性能極爲有害。 服務器
Linux內核如何管理物理內存對於數據庫服務器的性能而言也很重要。在 IA-32體系結構中, 內核基於 4KB大小的頁面管理內存。 另外一方面, 大多數當代的處理器都支持更大的頁面(高達數兆字節)。對於許多應用來講, 4KB頁面大小是理想的。小頁面能夠減小內部分段,將數據換入和換出內存時會產生更小的開銷,並確保使用中的虛存駐留於物理內存中。大部分數據庫服務器對於其數據庫緩衝區都使用大型共享內存段。其結果是須要大量頁表項(PageTableEntrie, PTE)。這給內存管理器添加了很大的維護開銷。 例如,倘若某個數據庫服務器使用 4MB大小的共享內存段爲其緩衝區分配 1GB共享內存。使用4KB頁面大小的內核須要 262 144個 PTE, 這個龐大的頁表數量會給內存管理器增添極大的維護開銷。 固然, 上述數據是過度簡化的計算值。 實際的 PTE數將遠大於這個數值,由於 Linux沒法對共享內存的頁表進行共享。
Linux 2.6內核中提供了對更大頁面的支持。進程能夠從內存池中顯式請求大頁面。使用大頁面能夠減小當應用請求大型內存塊時所需的 PTE數。所以, 維護 PTE所需的計算成本也得以減小。 對於前面的示例, 若是頁面大小是 4MB而不是 4KB, 那麼 1GB數據庫緩衝區只須要 1 024個 PTE(這個計算也被過分簡化)。大頁面支持特性的另外一個優勢是增長了 TLB(translation lookaside buffer)所覆蓋的內存範圍, 從而下降了 TLB不命中的機率。與頁表訪問相比較而言, TLB訪問的速度極快,由於它是 CPU緩存區域。
3、I/O 管理
數據庫性能嚴重依賴於高效快速的I/O操做。因爲有可能要處理 TB量級的數據,任何 I/O瓶頸都會致使數據庫服務器難以知足商業需求。 數據庫管理員(DBA)一般花費大量時間和金錢對 I/O子系統進行優化,以便減小 I/O延遲並最大化 I/O吞吐率。早期 Linux內核存在着許多阻礙 I/O性能的缺陷,也缺少諸如原始 I/O、向量 I/O、異步I/O以及直接 I/O等特性, 這限制了 DBA對在其餘平臺上已知可以改善數據庫性能的技術加以利用的能力。另外,功能上的匱乏,例如回彈緩衝和單個 I/O請求隊列鎖,增添了沒必要要的系統成本並引入了串行化問題。 幸運的是, 這些問題在 Linux 2.6內核中或經過對2.4內核打補丁都已被消除。
一、回彈緩衝區
在早期的 Linux 內核(早期的 2.4及先前的內核版本)中,設備驅動程序沒法直接訪問高端內存中的虛址。換句話說,這些設備驅動程序沒法對高端內存執行直接內存訪問I/O。相反, 內核在低端內存中分配緩衝區,數據經過內核緩衝區在高端內存和設備驅動程序之間傳輸。 這個內核緩衝區一般稱爲回彈緩衝區(bouncebuffer), 該過程被稱爲回彈或回彈緩衝。因爲數據庫服務器的 I/O密集特徵,回彈過程嚴重地下降了數據庫服務器的性能。首先,回彈緩衝區會消耗低端內存,這可能致使內存短缺問題。其次,過量的回彈操做會引發系統佔用時間較長, 致使數據庫系統徹底變成 CPU綁定的。數據庫服務器性能領域的一個主要進展便是在最近的內核中消除了回彈緩衝機制。
二、 原始I/O
Linux 2.4內核中引入的塊設備原始(raw)I/O接口提供了從用戶空間緩衝區直接執行I/O的能力,而沒必要經過文件系統接口進行額外複製。 raw接口的使用避免了文件系統層次上的操做,所以可以極大改進數據庫服務器的 I/O性能。然而,應該注意到,並不是全部的數據庫工做負荷都可以受益於 raw I/O的使用。若是須要常常訪問相同數據, raw I/O就沒法利用文件系統緩衝區 cache。raw I/O接口使得 DBA在針對性能目標而進行數據庫設計時具備更多的靈活性。 基於數據庫服務器的 I/O特徵, DBA可選擇使用 raw接口以得到更快的 I/O操做,或者使用文件系統緩存機制並減小磁盤訪問操做,或者組合使用上述兩種機制,這依賴於對數據庫中的表的訪問方式 。
三、 向量I/O
Linux 2.6內核經過readv和writev接口提供了向量I/O(vectored I/O,也稱scattered I/O)的完整實現。向量讀操做接口 readv將磁盤上的連續頁面讀入內存中的非連續頁面上;與之相反,向量寫操做接口 writev經過單個函數調用將內存中的非連續頁面寫到磁盤上。這種 I/O機制有利於頻繁執行大量串行 I/O操做的數據庫服務器。若是沒有正確的向量
讀寫實現,則執行串行 I/O的應用會完成如下操做之一:
- 執行數據庫頁面大小的 I/O操做。
- 執行大型塊 I/O操做,並使用 memcpy函數在讀/寫緩衝區與數據庫緩衝區之間複製數據頁面。
在掃描
TB
量級
(
這是當前數據倉庫的常見規模
)
的數據時,這兩種方法都會產生昂貴的計算開銷。
四、 異步I/O
異步I/O機制爲應用提供了發出 I/O請求後無需阻塞並等待該 I/O完成的能力。該機制很適合數據庫服務器。其餘平臺提供異步 I/O接口已有一段時間,但該特性在 Linux上還相對較新。在沒有異步 I/O機制的狀況下要提升 I/O吞吐率, 數據庫服務器一般建立許多專門執行 I/O的進程或線程。因爲大量進程/線程都在執行 I/O活動, 數據庫應用再也不阻塞於單個 I/O請求上。 使用大量進程/線程方式的缺點是建立、 管理和調度這些進程/線程會產生額外的開銷。
GNU C Library(GLIBC)異步 I/O接口經過用戶級線程來執行阻塞 I/O操做。這種方法只是使得請求對於應用而言看起來是異步的,但與前面描述的方法並沒有區別,也面臨着一樣的性能缺陷。爲了消除該問題, Linux 2.6 內核中引入了內核異步 I/O(Kernel AsynchronousI/O, KAIO)接口。 KAIO在內核而不是用戶空間中以線程方式實現異步 I/O
機制,確保了真正的異步性。
五、 直接I/O
直接 I/O具備可與原始 I/O相媲美的性能,又擁有文件系統的額外靈活性。所以對於但願在保持數據庫維護靈活性的同時又使用文件系統做爲存儲介質的數據庫管理員來講,直接I/O是具備吸引力的機制。
使用文件系統而不是 raw設備做爲存儲介質的主要吸引力是由於其易於調整數據庫存儲器的容量。只需添加更多的磁盤就能夠增長文件系統的大小。 文件系統的另外一個優勢是提供了許多可用的工具,例如, DBA可使用 fsck來幫助維護數據完整性。
將文件系統用做沒有直接 I/O接口的存儲介質也存在着一些缺點。其中之一就是緩衝區 cache守護進程所增長的開銷,該進程會主動地將髒頁面清空到磁盤上。這種活動所消耗的 CPU週期對於 CPU密集的數據庫工做負荷來講是寶貴資源;另外一個缺點與緩衝區cache不命中問題有關。若是數據不常常重用,其開銷會很大。
對於大型數據庫系統而言,會爲數據庫緩衝區分配內存。大型的數據庫緩衝區下降了數據庫應用的磁盤讀寫頻率,也減小了文件系統緩衝區 cache可用的內存量。這會對服務器性能產生雙面影響。首先, 緩衝區 cache守護進程更積極地將髒頁面清空到磁盤上(頁面更快地變髒)。 其次, 對於容量更小的緩衝區 cache, 數據駐留於其中的可能性要
小得多,這增長了緩衝區 cache不命中的可能性 。
六、塊I/O
設備驅動程序以稱爲塊的一組字節爲單位來傳輸數據。塊大小被設置爲設備的扇區大小,一般爲 512B(儘管許多硬件設備及其相關驅動程序能夠處理更大的傳輸文件)。 每一個塊在內存中都關聯着一個緩衝區頭部結構。當來自應用的讀請求經過read調用到達時,設備驅動程序將讀緩衝區劃分紅扇區大小的多個塊,在與每一個塊相關的緩衝區頭部裏填
充來自物理設備的數據,而後再將這些塊接合爲原始的讀緩衝區。相似地,當來自應用的一個寫請求到達時, 設備驅動程序將寫緩衝區劃分紅扇區大小的塊,並使用相關緩衝區頭部的取值來更新磁盤上的物理數據。在 Lnux2.6內核中,原始 I/O的塊大小爲 4096B而不是 512B。 這個簡單的變化經過減小原始 I/O操做所需的緩衝區頭部數量, 改進了總體 I/O吞吐率和 CPU利用率。緩衝區頭部更少的話,也能夠下降維護其所需的內核開銷,而大型塊的使用減小了設備驅動程序針對一個 I/O請求須要執行的劃分—接合操做數。
七、 I/O請求鎖
Linux內核爲每一個塊設備都維護一個 I/O請求隊列。 該隊列以一種最大化系統性能的方式對 I/O請求進行排序。在 Lnux 2.2和早期的 2.4內核中,全部的請求隊列由一個稱爲io_request_lock的全局自旋鎖加以保護。對於在尤許多磁盤構成的 SMP機器上運行的數據庫服務器來講,這個 I/O請求鎖會致使嚴重的串行化問題。
最近的內核版本里已從 SCSI子系統中刪除了這個全局鎖(io_request_lock)。在其位置上,每一個 I/O請求隊列都由本身的 request_queue_lock鎖加以保護。 I/O請求的串行化現象仍會出現,但只發生在單個請求隊列上,而不會發生在 SCSI子系統中的全部請求隊列上。
4、 小結
從 Linux 2.4版本轉換至 2.6版本後出現的大量內核變化改進了數據庫服務器性能。諸如多個運行隊列等特性的引入經過刪除系統中的串行點加強了 SMP擴展性。諸如向量I/O、異步 I/O和直接 I/O等變化所提供的內核服務已在其餘平臺上證實有助於提升數據庫性能。這些改進特性多數已包含在 SUSE或 RHEL基於 2.4內核的發行版本中。隨着Linux不斷地向數據庫服務器領域擴展,更多的性能瓶頸將會顯現出來,從而持續推進內核開發以改進性能,而且在此過程當中使得 Linux成爲各種數據庫應用工做負荷的一種更有吸引力的解決方案。