SQL Server新特性:內存數據庫

jopen 10年前發布 | 21K 次閱讀 SQLServer SQL Server 數據庫服務器

在傳統的數據庫表中,由于磁盤的物理結構限制,表和索引的結構為B-Tree,這就使得該類索引在大并發的OLTP環境中顯得非常乏力,雖然有很多 辦法來解決這類問題,比如說樂觀并發控制,應用程序緩存,分布式等。但成本依然會略高。而隨著這些年硬件的發展,現在服務器擁有幾百G內存并不罕見,此外 由于NUMA架構的成熟,也消除了多CPU訪問內存的瓶頸問題,因此內存數據庫得以出現。

SQL Server新特性:內存數據庫

內存的學名叫做Random Access Memory(RAM),因此如其特性一樣,是隨機訪問的,因此對于內存,對應的數據結構也會是Hash-Index,而并發的隔離方式也對應的變成了 MVCC,因此內存數據庫可以在同樣的硬件資源下,Handle更多的并發和請求,并且不會被鎖阻塞。

在SQL Server的Hekaton引擎由兩部分組成:內存優化表和本地編譯存儲過程。雖然Hekaton集成進了關系數據庫引擎,但訪問他們的方法對于客戶端是透明的,這也意味著從客戶端應用程序的角度來看,并不會知道Hekaton引擎的存在。

SQL Server新特性:內存數據庫

首先內存優化表完全不會再存在鎖的概念(雖然之前的版本有快照隔離這個樂觀并發控制的概念,但快照隔離仍然需要在修改數據的時候加鎖),此外內存優 化表Hash-Index結構使得隨機讀寫的速度大大提高,另外內存優化表可以設置為非持久內存優化表,從而也就沒有了日志(適合于ETL中間結果操作, 但存在數據丟失的危險)

SQL Server 2014內存數據庫針對傳統的表和存儲過程引入了新的結構: memory optimized table(內存優化表)和native stored procedure(本地編譯存儲過程)。

  • 默認情況下Memory optimized table是完全持久的(即為durable memory optimized table),如傳統的基于磁盤的表上的事務一樣,并且完全持久的事務也是支持原子、一致、隔離和持久 (ACID) 的。所不同的是內存優化表的整個表的主存儲是在內存中,即為從內存讀取表中的行,和更新這些行數據到內存中。 并非像是傳統基于磁盤的表按照數據庫數據庫頁面裝載數據庫。內存優化表的數據同時還在磁盤上維護著另一個副本,但僅用于持續性目的。 在數據庫恢復期間,內存優化的表中的數據再次從磁盤裝載。 除了默認持久的內存優化表之外,還支持non-durable memory optimized table(非持久化內存優化表),不記錄這些表的日志且不在磁盤上保存它們的數據。 這意味著這些表上的事務不需要任何磁盤 IO,但如果服務器崩潰或進行故障轉移,則無法恢復數據。
  • Native compiled stored procedure(本地編譯存儲過程)是針對傳統的存儲過程而言的,是本機編譯存儲過程后生成DLL,由于本機編譯是指將編程構造轉換為本機代碼的過 程,這些代碼由處理器指令組成,無需進一步編譯或解釋。與傳統TSQL 相比,本機編譯可提高訪問數據的速度和執行查詢的效率。故通過本機編譯的存儲過程,可在存儲過程中提高查詢和業務邏輯處理的效率。
  • </ul>

    內存數據庫既可以包含內存優化表和本地編譯存儲過程,又可以包含基于磁盤的表和傳統存儲過程,各個對象之間數據存儲、和訪問的架構如下所示:

    SQL Server新特性:內存數據庫

     

    內存數據庫的數據存儲

    內存數據庫的創建過程其實就是將表存放到內存中,而不是整個數據庫。在內存數據庫中,磁盤上存儲的數據文件不在是區、頁的存儲方式,而是基于文件流 存儲。文件流存儲的一個特點之一就是支持快速的讀操作,這在數據庫重啟時將文件流中的數據load到內存中時很能提高效率。內存數據庫的數據文件分 data file和delta file,而且是成對出現,內存數據庫中插入、更新的數據和刪除的數據物理分開存儲的,分別用data file和delta file保存。

    1、Data file

    Data file用來保存”插入”或者”更新”的數據行,data file中數據行的存儲順序嚴格按照事務執行的順序組織,比如data file中第一行的數據來自于事務1,第二行數據來自于事務2,這兩行可以是同一個表的數據,也可以是不同表的數據,取決于這兩個連續的事務操作的內存優 化表是否相同。 這種方式的好處是保證了磁盤IO的連續性,避免隨機IO。

    Data file的大小是固定的,為128MB,當一個data file被寫滿了后,SQL會自動新建一個data file。因為數據在data file中保存的順序是按照事務的執行順序進行的,所以一張表的數據行(來自多個事務)可能跨越了多個data file,當對多行進行更新操作時,寫操作可以分配到多個文件上,并且同時進行,這樣就可以加快更新的效率。

    如下圖,一共有4個data files(淺藍色),第一個data file的事務范圍為100-200,第二個data file的事務范圍為200-300……(100、200表示時間戳)

    SQL Server新特性:內存數據庫

    在Data file中,如果一行被刪除或者更新了,這行不會從data file中移除,而是通過delta file(上圖黃色框)來標記刪除的行,(update的本質是delete和insert的集合,所以執行update時也會有刪除的動作),這樣可以 消除不必要的磁盤IO。

    如果data file的數據永不刪除,那文件豈不是無限制的增大,以后備份不是得用很大的磁盤才行?當然不是,SQL在處理這個問題用到方法其實很簡單——”合并”, 根據合并策略,將多個data file和delta file合并起來,依據delta file的內容刪除data file中的多余記錄,然后將多個data file合并成一個文件,從而減小數據文件占用的磁盤空間大小。

    2、Delta file

    每個data file都有一個與之匹配的Delta File,這個匹配是指事務范圍上的匹配,兩者記錄的是同一段事務(包括一個或者多個事務)上的數據,Delta File中記錄了data file中被刪除行的標記,這個標記其實就是一個關聯信息{inserting_tx_id, row_id, deleting_tx_id }。它跟data file一樣,也是嚴格按照事務操作的順序來保存刪除的行的信息。

    SQL Server新特性:內存數據庫

    如上圖,該內存數據庫有5個data file,分別存放了事務范圍在100-200、200-300、300-400、400-500及500的數據。如果有一個時間戳為501的事務需要刪 除時間戳為150、250、450的事務所產生的數據和增加一些新數據時,相應的IO請求就會被分配到第1、2、4的 delta file上和第5的data file上。刪除操作可以分配到多個文件上,并且同時進行,這樣就可以加快刪除的效率。

    內存優化表存儲結構

    內存優化表是基于行版本存儲的,同一行在內存中會有多個版本,可以將內存優化表的存儲結構看作是該表中所有行的多個行版本的集合。內存優化表中的行跟傳統數據庫的行結構是不一樣的,下圖描述了內存優化表中一行的數據結構:

    SQL Server新特性:內存數據庫

    在內存優化表中,一行有兩個大部分組成:Row header和Row body,

    • Row header記錄這個行的有效期(開始時間戳和結束時間戳)和索引指針
    • Row body記錄了一行的實際數據。
    • </ul>

      在內存優化表中,行版本的數量是由針對該行的操作次數決定的,比如:每更新一次,就會新產生一行,增加一個行版本,新行有新的開始時間戳,新行產生后,原來的數據行會自動填充結束時間戳,意味這行已經過期。

      SQL Server新特性:內存數據庫

      備注:上圖實際上只有3行,第1行有3個行版本,第2行有2個行版本,第3行有4個行版本。

      在傳統數據庫中,表中每一行都是唯一的,一個事務如想找到一行,通過文件號、頁號、槽位就可以了。在內存數據庫中,每一行有多個行版本,一個事務不 可能對將每個行版本都操作一遍,實際上,一個事物只能操作同一行的一個行版本,至于它能對哪個行版本進行操作,取決于事務執行時間是否在這行的兩個時間戳 之間。除此之外的其他行版本對該事務而言是不可見的。由于一行可能存在多個行版本,一張上百萬行的表,內存哪夠呀。前文介紹過了,每個行實際上是有時間戳 的,對于已經打上結束時間戳且沒有活動事務訪問的行,SQL Server會通過garbage collection機制回收它占用的內存,從而節省內存。所以不要擔心內存不夠。

      內存數據庫的鎖

      鎖的一個重要作用就是避免多個進程同時修改數據,從而造成數據不一致。常見的沖突現象包括讀寫互鎖和寫寫互鎖。那內存數據庫是如何通過行版本來解決這兩種鎖定現象的呢?

      1、讀寫互鎖

      在內存數據庫中,所有對內存優化表的事務隔離都是基于快照的,準確的說是基于行的快照。從上文行的 結構可以知道,每行的行頭包括開始時間戳和結束時間戳的,一個事務能不能訪問到這行關鍵在于事務的啟動時間是不是在這行的兩個時間戳內。如果某個事務正在 修改一行(快照),但還未提交到內存優化表中,也就是說”新行”還沒有結束時間戳,對”讀事務”而言,它讀還是是原來行(快照),因此不會存在臟讀的現 象。

      2、寫寫互鎖

      兩個事務同時更新一行時,就會發生寫寫互鎖。內存數據庫沖突發生的概率比傳統數據庫小很多,但如果實在遇到了沖突,只能調整應用程序,在應用程序中加入”重試邏輯”(等待一會,然后再重新發起事務)來解決。

      或許有同學覺得這種方式好像也沒有什么大的性能改變。其實不然,舉個例子,在傳統數據庫中一個鎖可能將整個表都管住了,在表鎖期間只能等待這個事務 做完才能執行其他事務,而實際上這個事務可能只是修改了小部分行,因為表鎖的存在,其他行那些不需要被這個事務操作的行。但內存數據庫中寫寫沖突總是發生 在行級別的,這個粒度小多了,影響沒這么大。

      內存數據庫的持久性

      1、事務日志

      內存數據庫的”寫日志”和”寫數據”在一個事務中進行,在事務執行期間,SQL會先”寫數據”然后在才”寫日志”,這點與傳統數據庫不同,在傳統數 據庫中,不管是在內存中還是磁盤中,”寫數據”總是在”寫日志”之后,也就是通常所說的WAL(Write-Ahead Transaction Log)。但是,在事務提交時,內存數據庫和傳統數據庫在”寫日志”上沒有什么區別:日志會先于數據寫入到磁盤中。因此,即使服務器發生了宕機或者斷電, 下次數據庫重啟時會按照已經保存在磁盤中事務日志將業務redo(重做),所以不要擔心數據會丟失。另外,內存數據庫只會對持久性表將已提交的事物日志保 存到磁盤中。這樣做的好處可以減少寫磁盤的次數。內存數據庫支持頻繁、快速的增、刪、改等操作,這個強度遠遠高于傳統數據庫,數據庫需要為每筆操作寫日 志,這樣就會產生大量磁盤IO,寫日志操作將有可能成為性能瓶頸,不記錄未提交的事務日志就減少寫日志的數量,從而可以提高數據庫的性能。

      2、CheckPoint

      在內存數據庫中,CheckPoint的主要目的就是將內存中的”數據”寫入到磁盤中,從而在數據庫崩潰或者重啟時減少數據恢復的時間。不需要數據 庫逐條讀取所有的日志來恢復數據。默認情況下Checkpoint是周期性進行的,當日志至上次checkpoint后增加了512M時會觸發新一輪 CheckPoint。在傳統數據庫這種,Checkpoint可以將未提交的數據flush到磁盤的mdf文件中,這個現象在內存數據庫中不會發生,因 為內存數據庫只將已提交事務的日志,而在寫日志(到磁盤)之前不可能將數據先寫到磁盤中,因此可以保證寫到磁盤中的數據一定是已提交事務的數據。

      內存數據庫應用場景

      傳統基于磁盤的表,通常會遇到內存頁面置換、死鎖、造成了吞吐量有限、事務延遲較長等問題,內存數據庫的內存優化表由于常駐內存,適用于低延遲、高并發、快速數據傳輸和裝載等場景。各場景的使用、機制具體如下:

      低延遲:由于內存優化表和本地編譯存儲過程直接生成DLL,本機編譯可提高訪問數據的速度和執行查詢的效率響應速度快,作為參與處理業務邏輯的存儲過程而言,大大降低了存儲過程作為中間層執行和訪問的效率。提高了應用的訪問效率,降低了延遲性。內存優化表的創建和裝載過程如下:

      SQL Server新特性:內存數據庫

      本地編譯存儲過程的創建和裝載過程如下:

      SQL Server新特性:內存數據庫

      高吞吐量:由于內存優化表直接從內存中讀取、寫入數據,當訪問數據時,不再使用latch,故不同于基于磁盤的表,對于insert/update/delete的操作,latch爭用、以及死鎖問題隨即消失。

      SQL Server新特性:內存數據庫

      與此同時,可大大提高了應用的吞吐量。 隨著配置的增加,其性能呈直線上升。

      SQL Server新特性:內存數據庫

      快速數據傳輸、裝載:由于非持久化內存優化表僅常駐內存,并無基于磁盤的副本。當需要將一些外部數據通過ETL裝載到內存數據庫,可以使用無任何IO和logging的非持久化內存優化表作為過渡表,可有效的加快裝載數據庫的速度。

      SQL Server新特性:內存數據庫

      內存數據庫所需資源

      內存數據庫在使用硬件資源與傳統表有著一定的特殊性,為了提高內存數據庫性能,對存儲內存數據庫的各方面的資源有著比傳統數據庫更高的要求。可參考如下具體需求:

      • 內存:所有內存優化表是常駐內存的,因此需足夠的物理內存來存儲內存優化表。但這并不意味著需要將整個數據庫放入內存中,而是僅將頻繁訪問的熱數據常駐內存優化表中。且最高可以支持到256GB的數據量。
      • 磁盤:同樣存在log和data兩類文件。Log文件依然記錄事務信息。針對于持久性的內存優化表,為了降低log IO的競爭、保證低延遲,一般建議至少SSD。
      • CPU:可根據OLTP環境的負載考慮CPU的配置,如兩個CPU socket支撐一個中等級別的服務器。
      • Network:針對于單機的內存數據庫,由于數據存儲于數據庫服務器的內存中,對于數據交互仍然為應用層到數據層的訪問,如以往數據交互,對于 網絡并未有較高的依賴性。對于內存數據庫應用于數據庫高可用和異地災備的情況下(如同步/異步模式的Always-on),同一數據中心的網絡延遲,以及 不同數據中的網絡延遲對于使用與高可用性和災備的內存數據庫的事務有一定量的影響。
      • </ul>

        參考資料:

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!