在逝去的2016后半年,由于项目需要支持数据的快速更新和多用户的高并发负载,我试水SQL Server 2016的In-Memory OLTP,创建内存数据库实现项目的负载需求,现在项目接近尾声,系统运行稳定,写一篇博客,记录一下使用内存数据库的经验。
SQL Server 2016的In-Memory OLTP,通俗地讲,是内存数据库,使用内存优化表(Memory-Optimized Table,简称MOT)来实现,MOT驻留在内存中,使用 Hekaton 内存数据库引擎访问。在查询MOT时,只从内存中读取数据行,不会产生Disk IO消耗;在更新MOT时,数据的更新直接写入到内存中。内存优化表能够在Disk上维护一个数据副本,该副本只用于持久化数据,不用于数据读写操作。
在内存数据库中,不是所有的数据都需要存储在内存中,有些数据仍然能够存储在Disk上,硬盘表(Disk-Based Table,简称DBT)是传统的表存储结构,每个Page是8KB,在查询和更新DBT时,产生Disk IO操作,将数据从Disk读取到内存,或者将数据更新异步写入到Disk中。
内存数据库将原本存储在Disk上的数据,存储在内存中,利用内存的高速访问优势实现数据的快速查询和更新,但是,内存数据库,不仅仅是存储空间的变化,Hekaton 内存数据库访问引擎实现本地编译模块(Natively compiled),交叉事务(Cross-Container Transaction)和查询互操作(Query Interop):
内存数据被整合到SQL Server关系引擎中,使用内存数据库时,客户端应用程序甚至感受不到任何变化,DAL接口也不需要做任何修改。由于Query Interop的存在,任何解释性TSQL脚本都能透明地访问MOT,只是性能没有本地编译TSQL脚本性能高。在使用分布式事务访问MOT时,必须设置合适的事务隔离级别,推荐使用Read Committed,如果发生MSSQLSERVER_41333 错误,说明产生交叉事务隔离错误(CROSS_CONTAINER_ISOLATION_FAILURE),原因是当前事务的隔离级别太高。
一,创建内存数据库
内存优化表的数据必须存储在包含Memory_Optimized_Data的File Group中,该FileGroup可以有多个File,每个File实际上是Folder,一个DB只能创建一个包含Memory_Optimized_Data的File Group。
step1,创建一个数据库,创建的Data File的数量最好和CPU内核数量保持一致,存放在不同的物理磁盘上;
use master Test_MemboryDB on Primary ( name=Test_MemoryDB_1, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_2, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_3, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_4, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_5, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_6, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_7, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_8, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_9, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_10, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_11, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_12, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_13, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_14, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_15, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_16, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_17, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_18, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_19, filename, size=5GB, FileGrowth=1GB ), ( name=Test_MemoryDB_20, filename, size=5GB, FileGrowth=1GB ) LOG ON ( name , filename , size = 10GB , filegrowth = 1GB ) GO
View Codestep2,为数据库创建一个包含内存优化数据的FileGroup,向该FileGroup中添加“File”,实际上是目录(Directory),用于存储内存优化数据文件,主要是CheckPoint文件,用于还原持久化的内存优化表。