Published on

January 13, 2016

Понимание оптимистической многоверсионной конкурентности в SQL Server

InMemory – потрясающая концепция, и мне посчастливилось узнать о ней от своих друзей в индустрии через блоги. Она содержит глубокие концепции и иногда сложно понять, как все строится. В этом блоге мы рассмотрим концепцию оптимистической многоверсионной конкурентности в SQL Server и как она реализуется.

Оптимистическая многоверсионная конкурентность – это концепция в SQL Server, которая позволяет нескольким транзакциям одновременно получать доступ и изменять данные без блокировки друг друга. Это достигается созданием нескольких версий данных и позволяет каждой транзакции работать со своей собственной версией.

Давайте начнем с создания базы данных и таблицы для экспериментов. Вот скрипт:

USE [master] 
GO
-- Этот оператор работает только с SQL Server 2016
-- Измените его соответствующим образом, если вы используете более ранние версии
DROP DATABASE IF EXISTS  [InMem_OLTP] 
GO
CREATE DATABASE [InMem_OLTP] ON  PRIMARY
( NAME = N'InMem_OLTP_data', FILENAME = N'C:\DATA\InMem_OLTP_data.mdf', 
SIZE = 20480KB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB), 
FILEGROUP [InMem_OLTP_InMemory] CONTAINS MEMORY_OPTIMIZED_DATA  DEFAULT
( NAME = N'InMem_OLTP_InMemory', FILENAME = N'C:\Data\InMem_OLTP_mopt', 
MAXSIZE = UNLIMITED)
LOG ON
( NAME = N'InMem_OLTP_log', FILENAME = N'C:\DATA\InMem_OLTP_log.ldf', 
SIZE = 20480KB, FILEGROWTH = 10%)
GO 

-- Создание таблицы для экспериментов
USE [InMem_OLTP] 
GO
CREATE TABLE dbo.SalesOrder_inmem
(
order_id INT IDENTITY NOT NULL,
order_date DATETIME NOT NULL,
order_status tinyint NOT NULL,
amount FLOAT NOT NULL,
CONSTRAINT PK_SalesOrderID PRIMARY KEY NONCLUSTERED 
HASH (order_id) WITH (BUCKET_COUNT = 10000)
) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)
GO
INSERT INTO dbo.SalesOrder_inmem VALUES
('1/1/2010',1,1000),
('1/1/2011',1,2000),
('1/1/2012',1,3000),
('1/1/2013',1,4000),
('1/1/2014',1,5000)

Теперь давайте разберемся с оптимистической частью многоверсионной конкурентности. Мы создадим сценарий с двумя сессиями и наблюдаем, как SQL Server обрабатывает конкурентность.

-- Сессия 1
BEGIN TRANSACTION
INSERT INTO dbo.SalesOrder_inmem VALUES
('1/1/2015',1,6000)

-- Сессия 2
SELECT * FROM dbo.SalesOrder_inmem

В приведенном выше сценарии у нас есть две сессии. В сессии 1 мы вставляем новую запись в таблицу. В сессии 2 мы пытаемся прочитать из таблицы. Однако мы видим только существующие 5 записей, а 6-я запись, вставленная в сессии 1, не видна. Это происходит потому, что транзакция в сессии 1 все еще открыта, и SQL Server создал версию данных, чтобы гарантировать, что запрос в сессии 2 не блокируется. Как только мы фиксируем транзакцию в сессии 1, дополнительная запись автоматически появляется в сессии 2.

-- Сессия 1
COMMIT

-- Сессия 2
SELECT * FROM dbo.SalesOrder_inmem

Теперь давайте подробнее рассмотрим многоверсионность. Мы обновим запись и наблюдаем различные версии данных.

-- Сессия 1
BEGIN TRANSACTION
UPDATE dbo.SalesOrder_inmem WITH (SNAPSHOT)
SET amount = 10000
WHERE order_id = 6

-- Сессия 2
SELECT * FROM dbo.SalesOrder_inmem

В приведенном выше сценарии мы обновляем значение amount в сессии 1. Однако обновленное значение не видно в сессии 2 до тех пор, пока транзакция в сессии 1 не будет зафиксирована. Это демонстрирует возможность SQL Server поддерживать несколько версий записей в таблице InMemory.

Надеюсь, этот блог-пост помог вам более ясно понять, как работают таблицы InMemory в оптимистической модели конкурентности. Если у вас есть вопросы или вам нужна большая ясность по любому аспекту, не стесняйтесь обращаться ко мне.

Счастливого кодирования!

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.