在逝去的2016后半年,由于項(xiàng)目需要支持?jǐn)?shù)據(jù)的快速更新和多用戶的高并發(fā)負(fù)載,我試水SQL Server 2016的In-Memory OLTP,創(chuàng)建內(nèi)存數(shù)據(jù)庫(kù)實(shí)現(xiàn)項(xiàng)目的負(fù)載需求,現(xiàn)在項(xiàng)目接近尾聲,系統(tǒng)運(yùn)行穩(wěn)定,寫(xiě)一篇博客,記錄一下使用內(nèi)存數(shù)據(jù)庫(kù)的經(jīng)驗(yàn)。
SQL Server 2016的In-Memory OLTP,通俗地講,是內(nèi)存數(shù)據(jù)庫(kù),使用內(nèi)存優(yōu)化表(Memory-Optimized Table,簡(jiǎn)稱MOT)來(lái)實(shí)現(xiàn),MOT駐留在內(nèi)存中,使用 Hekaton 內(nèi)存數(shù)據(jù)庫(kù)引擎訪問(wèn)。在查詢MOT時(shí),只從內(nèi)存中讀取數(shù)據(jù)行,不會(huì)產(chǎn)生Disk IO消耗;在更新MOT時(shí),數(shù)據(jù)的更新直接寫(xiě)入到內(nèi)存中。內(nèi)存優(yōu)化表能夠在Disk上維護(hù)一個(gè)數(shù)據(jù)副本,該副本只用于持久化數(shù)據(jù),不用于數(shù)據(jù)讀寫(xiě)操作。
在內(nèi)存數(shù)據(jù)庫(kù)中,不是所有的數(shù)據(jù)都需要存儲(chǔ)在內(nèi)存中,有些數(shù)據(jù)仍然能夠存儲(chǔ)在Disk上,硬盤(pán)表(Disk-Based Table,簡(jiǎn)稱DBT)是傳統(tǒng)的表存儲(chǔ)結(jié)構(gòu),每個(gè)Page是8KB,在查詢和更新DBT時(shí),產(chǎn)生Disk IO操作,將數(shù)據(jù)從Disk讀取到內(nèi)存,或者將數(shù)據(jù)更新異步寫(xiě)入到Disk中。
內(nèi)存數(shù)據(jù)庫(kù)將原本存儲(chǔ)在Disk上的數(shù)據(jù),存儲(chǔ)在內(nèi)存中,利用內(nèi)存的高速訪問(wèn)優(yōu)勢(shì)實(shí)現(xiàn)數(shù)據(jù)的快速查詢和更新,但是,內(nèi)存數(shù)據(jù)庫(kù),不僅僅是存儲(chǔ)空間的變化,Hekaton 內(nèi)存數(shù)據(jù)庫(kù)訪問(wèn)引擎實(shí)現(xiàn)本地編譯模塊(Natively compiled),交叉事務(wù)(Cross-Container Transaction)和查詢互操作(Query Interop):
本地編譯模塊:如果代碼模塊只訪問(wèn)MOT,那么可以將該模塊定義為本地編譯模塊,SQL Server直接將TSQL腳本編譯成機(jī)器代碼;SQL Server 2016支持本地編譯的模式有:存儲(chǔ)過(guò)程(SP),觸發(fā)器(Trigger),標(biāo)量值函數(shù)(Scalar Function)或內(nèi)嵌多語(yǔ)句函數(shù)(Inline Multi-Statement Function)。相比于解釋性(Interpreted)TSQL 模塊,機(jī)器代碼直接使用內(nèi)存地址,性能更高。
交叉事務(wù):在解釋性TSQL模塊中,一個(gè)事務(wù)既能訪問(wèn)硬盤(pán)表,也能訪問(wèn)內(nèi)存優(yōu)化表;實(shí)際上,SQL Server創(chuàng)建了兩個(gè)事務(wù),一個(gè)事務(wù)用于訪問(wèn)硬盤(pán)表,一個(gè)事務(wù)用于訪問(wèn)內(nèi)存優(yōu)化表,在DMV中,分別使用transaction_id 和 xtp_transaction_id 來(lái)標(biāo)識(shí)。
查詢互操作:解釋性TSQL腳本能夠訪問(wèn)內(nèi)存優(yōu)化表和硬盤(pán)表,本地編譯模塊只能訪問(wèn)內(nèi)存優(yōu)化表。
內(nèi)存數(shù)據(jù)被整合到SQL Server關(guān)系引擎中,使用內(nèi)存數(shù)據(jù)庫(kù)時(shí),客戶端應(yīng)用程序甚至感受不到任何變化,DAL接口也不需要做任何修改。由于Query Interop的存在,任何解釋性TSQL腳本都能透明地訪問(wèn)MOT,只是性能沒(méi)有本地編譯TSQL腳本性能高。在使用分布式事務(wù)訪問(wèn)MOT時(shí),必須設(shè)置合適的事務(wù)隔離級(jí)別,推薦使用Read Committed,如果發(fā)生MSSQLSERVER_41333 錯(cuò)誤,說(shuō)明產(chǎn)生交叉事務(wù)隔離錯(cuò)誤(CROSS_CONTAINER_ISOLATION_FAILURE),原因是當(dāng)前事務(wù)的隔離級(jí)別太高。
一,創(chuàng)建內(nèi)存數(shù)據(jù)庫(kù)
內(nèi)存優(yōu)化表的數(shù)據(jù)必須存儲(chǔ)在包含Memory_Optimized_Data