内存中OLTP(Hekaton)里的事务日志记录

在今天的文章里,我想详细讨论下内存中OLTP里的事务日志如何写入事务日志。我们都知道,对于你的内存优化表(Memory Optimized Tables),内存中OLTP提供你2个持久性(durability)选项:

  • SCHEMA_ONLY
  • SCHEMA_AND_DATA

今天我不想更多讨论SCHEMA_ONLY,因为使用这个选项,在事务日志里没有发生任何日志(SQL Server 重启后你的数据会丢失)。今天我们会专门讲解下SCHEMA_AND_DATA选项的持久性。

SCHEMA_AND_DATA

使用SCHEMA_AND_DATA持久性选项,SQL Server必须记录你的事务到事务日志,因为每个内存中OLTP事务必须总是持久的。这个和传统基于硬盘表是一样的。但是内存中OLTP里写入事务日志比传统表更优化。内存中OLTP支持多个并发日志流(在SQL Server 2014里当前未实现),内存中OLTP只记录发生的逻辑事务(logical transaction)

逻辑事务是什么意思呢?假设你有5个非聚集索引定义的聚集表。如果你往表里插入1条记录,SQL Server必须记录插入到聚集索引,还有5个额外的插入非聚集索引。在你表上定义的非聚集索引越多,SQL Server需要的日志越多。而且SQL Server只能和事务日志一样快。

使用内存中OLTP事情就变了。内存中OLTP,SQL Server只记录在你事务里发生的逻辑修改。SQL Server对在你哈希或范围索引里的修改不记录。因此1条日志记录只描述发生的逻辑INSERT/UPDATE/DELETE语句。结果是,内存中OLTP写入更少的数据到你的事务日志,因此你的事务可以更快的提交。

我们来验证它!

我想用1个简单的例子向你展示下,当你首先插入10000条记录到传统基于硬盘表(Disk Based Table),然后插入内存优化表(Memory Optimized Table),SQL Server会有多少的数据写入你的事务日志。下列代码创建1个简单表,在while循环里插入10000条记录。然后我用sys.fn_dblog系统函数(未文档公开)来看事务日志。

 1 -- Create a Disk Based table
 2 CREATE TABLE TestTable_DiskBased
 3 (
 4     Col1 INT NOT NULL PRIMARY KEY,
 5     Col2 VARCHAR(100) NOT NULL INDEX idx_Col2 NONCLUSTERED,
 6     Col3 VARCHAR(100) NOT NULL
 7 )
 8 GO
 9
10 -- Insert 10000 records into the table
11 DECLARE @i INT = 0
12
13 BEGIN TRANSACTION
14 WHILE (@i < 10000)
15 BEGIN
16     INSERT INTO TestTable_DiskBased VALUES (@i, @i, @i)
17
18     SET @i += 1
19 END
20 COMMIT
21 GO
22
23 -- SQL Server logged more than 20000 log records, because we have 2 indexes
24 -- defined on the table (Clustered Index, Non-Clustered Index)
25 SELECT * FROM sys.fn_dblog(NULL, NULL)
26 WHERE PartitionId IN
27 (
28     SELECT partition_id FROM sys.partitions
29     WHERE object_id = OBJECT_ID(‘TestTable_DiskBased‘)
30 )
31 GO

从系统函数的输出你可以看到,你有比20000多一点的日志记录。这是正确的,因为我们在表上有2个索引定义(1个聚集索引,1个非聚集索引)。

现在我们来看下用内存优化表(Memory Optimized Table)日志记录有啥改变。下列代码展示了为内存中OLTP数据库必备工作:我们只加了1个新的内存优化文件组(Memory Optimized File Group),给它加了个容器:

 1 --Add MEMORY_OPTIMIZED_DATA filegroup to the database.
 2 ALTER DATABASE InMemoryOLTP
 3 ADD FILEGROUP InMemoryOLTPFileGroup CONTAINS MEMORY_OPTIMIZED_DATA
 4 GO
 5
 6 USE InMemoryOLTP
 7 GO
 8
 9 -- Add a new file to the previously created file group
10 ALTER DATABASE InMemoryOLTP ADD FILE
11 (
12     NAME = N‘InMemoryOLTPContainer‘,
13     FILENAME = N‘C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\InMemoryOLTPContainer‘
14 )
15 TO FILEGROUP [InMemoryOLTPFileGroup]
16 GO

下一步我创建了1个新的内存优化表(Memory Optimized Table)。这里我在哈希索引上选择了16384的桶数来避免哈希碰撞(hash collisions)的可能。另外我在Col2和Col3列上创建了2个范围索引(Range Indexes)。

 1 -- Creates a Memory Optimized table
 2 CREATE TABLE TestTable_MemoryOptimized
 3 (
 4     Col1 INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 16384),
 5     Col2 VARCHAR(100) COLLATE Latin1_General_100_Bin2 NOT NULL INDEX idx_Col2,
 6     Col3 VARCHAR(100) COLLATE Latin1_General_100_Bin2 NOT NULL INDEX idx_Col3
 7 ) WITH
 8 (
 9     MEMORY_OPTIMIZED = ON,
10     DURABILITY = SCHEMA_AND_DATA
11 )
12 GO

在那个表上合计有3个索引(1个哈希索引(Hash Index)和2个范围索引(Range Indexes))。当你往表里插入10000条记录,传统表会生成近30000的日志记录——每个索引里每个插入1条日志。

 1 -- Copy out the highest ‘Current LSN‘
 2 SELECT * FROM sys.fn_dblog(NULL, NULL)
 3 GO
 4
 5 -- Insert 10000 records into the table
 6 DECLARE @i INT = 0
 7
 8 BEGIN TRANSACTION
 9 WHILE (@i < 10000)
10 BEGIN
11     INSERT INTO TestTable_MemoryOptimized VALUES (@i, @i, @i)
12
13     SET @i += 1
14 END
15 COMMIT
16 GO
17
18 -- Just a few log records!
19 SELECT * FROM sys.fn_dblog(NULL, NULL)
20 WHERE [Current LSN] > ‘0000002f:000001c9:0032‘ -- Highest LSN from above
21 GO

但现在当你看事务日志时,你会看到10000条插入只生成了很少日志记录——这里是17条!

魔法发生在LOP_HK日志记录里。在这个特定日志记录里,内存中OLTP捆绑了多个修改到你的内存优化表(Memory Optimized Table)。你也可以通过使用sys.fn_dblog_xtp系统函数分解LOP_HK日志记录:

1 -- Let‘s look into a LOP_HK log record
2 SELECT * FROM sys.fn_dblog_xtp(NULL, NULL)
3 WHERE [Current LSN] > ‘0000002f:000001c9:0032‘ AND Operation = ‘LOP_HK‘
4 GO

从图中你可以看到,内存中OLTP只生成了近10000条LOP_HK日志记录——在这个表上发生的每个逻辑插入对应1条记录。

小结

内存中OLTP提供你惊艳的性能提升,因为它是基于全新原理,例如MVCC和Lock-Free Data Structrues。另外它只生成少量事务日志记录,因为只有逻辑改变被记录写入事务日志。我希望这个文章已给你更好的理解:内存中OLTP如何提升你的事务日志吞吐量。

感谢关注!

时间: 2024-10-29 10:46:15

内存中OLTP(Hekaton)里的事务日志记录的相关文章

SQL Server 内存中OLTP内部机制概述(三)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx 译者水平有限,如有翻译不当之处,欢迎指正. ----------------------------我是分割线---------------

SQL Server 内存中OLTP内部机制概述(二)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx 译者水平有限,如有翻译不当之处,欢迎指正. ----------------------------我是分割线---------------

为什么我还不推荐内存中OLTP给用户

嗯,有些人在看玩这篇文章后会恨我,但我还是要说.1个月来我在内存中OLTP这个里领域里做了大量的工作,很多用户都请求使用这个惊艳的新技术.遗憾的是,关于内存中OLTP没有一个是真的令人激动的——看完你就知道了. 内存中OLTP有问题么? 没有!真的!我喜欢这个惊艳的新技术,但我还不能推荐它给任何用户.就这样!很有用户现在还运行在SQL Server 2008(R2)上,他们就想迁移到SQL Server 2014上.这个惊艳新技术给他们100倍的吞吐量提升.因此让我们来用它吧!遗憾的是并不简单.

内存中OLTP(Hekaton)的排序警告

内存中OLTP是关于内存中的一切.但那只是对了一半.在今天的文章里我想给你展示下,当你从内存读取数据时,即使内存中OLTP也会引起磁盘活动.这里的问题是执行计划里,不正确的统计信息与排序(sort)运算符的组合. 排序(sort)运算符问题 我们都知道,排序(sort)运算符需要所谓的内存授予(Memory Grant)来作它的运行.内存区域是用来进行执行计划里到来记录的排序.内存授予的大小是基于估计行数数量.在基数计算(Cadinality Estimation)期间查询优化器估计执行计划里每

SQL Server 内存中OLTP内部机制概述(一)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx ----------------------------我是分割线------------------------------- SQL S

SQL Server 2014新功能 -- 内存中OLTP(In-Memory OLTP)

SQL Server 2014新功能 -- 内存中OLTP(In-Memory OLTP) 概述 内存中OLTP(项目"Hekaton")是一个全新的.完全集成到SQL Server的数据库引擎组件. 对OLTP工作负载访问中在内存中的数据进行了优化.内存中OLTP能够帮助OLTP工作负载实现显著的性能改善,并减少处理时间.表能被视为"内存优化",提升内存中的OLTP功能.内存优化表是完全可事务的.并可以使用Transact-SQL进行访问.Transact-SQL

SQL Server 内存中OLTP内部机制概述(四)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx 译者水平有限,如有翻译不当之处,欢迎指正. ----------------------------我是分割线---------------

(转)解释一下SQLSERVER事务日志记录

本文转载自桦仔的博客http://www.cnblogs.com/lyhabc/archive/2013/07/16/3194220.html 解释一下SQLSERVER事务日志记录 大家知道在完整恢复模式下,SQLSERVER会记录每个事务所做的操作,这些记录会存储在事务日志里,有些软件会利用事务日志来读取 操作记录恢复数据,例如:log explorer 那么事务日志记录怎麽查看,里面都记录了些什么? 打开可以利用下面SQL语句来查看所在数据库的事务日志记录 1 USE [GPOSDB] -

SQL Server中的事务日志管理(6/9):大容量日志恢复模式里的日志管理

当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会告诉你每个DBA应该知道的具体细节. 这个标题有点用词不当,因为运行在大容量日志恢复模式里的数据库,我们通常是长期不管理日志.但是,DBA会考虑在大容量加载时,短期切换到大容量恢复模式.当数据库在大容量模式里运行时,一些其他例如索引重建的操作会最小化日志(minimally logged),因此在日