zoukankan      html  css  js  c++  java
  • 内存中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 FilesMicrosoft SQL ServerMSSQL12.MSSQLSERVERMSSQLDATAInMemoryOLTPContainer'
    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如何提升你的事务日志吞吐量。

    感谢关注!

    参考文章:

    https://www.sqlpassion.at/archive/2015/03/09/transaction-logging-memory-oltp-hekaton/

  • 相关阅读:
    MySQL基础之第9章 触发器
    Windows系统安装————windows7 企业版 无法安装 NET.framework4.52-4.6版本在WIN7下解决办法
    流媒体技术学习笔记之(十二)Linux(Ubuntu)环境运行EasyDarwin
    流媒体服务器之————EasyDarwin开源流媒体服务器:编译、配置、部署
    流媒体技术学习笔记之(十一)Windows环境运行EasyDarwin
    流媒体技术学习笔记之(十)HLS协议直播延时优化(35s到10S)
    流媒体技术学习笔记之(九)减少VLC 延迟的方法
    流媒体技术学习笔记之(八)海康、大华IpCamera RTSP地址和格式
    流媒体技术学习笔记之(七)进阶教程OBS参数与清晰度流畅度的关系
    Phalcon框架之———— 2.0升级到3.0 问题Model验证问题解决
  • 原文地址:https://www.cnblogs.com/woodytu/p/4716171.html
Copyright © 2011-2022 走看看