2.10.25

Когда добавляются теги версионирования?

Автор: Paul Randal, Inside the Storage Engine: When do versioning tags get added?

Ходит популярное мнение, что если включить моментальные снимки (snapshot isolation), а затем перестроить индексы, то все строки таблицы получат дополнительные 14-байтовые теги версионирования. Правда это или миф? Давайте проверим.

Сначала я создам тестовую базу данных с небольшой таблицей, кластерным индексом и несколькими строками:

CREATE DATABASE SItest;
GO

USE SItest;
GO

CREATE TABLE SmallTable (c1 INT, c2 INT);CREATE CLUSTERED INDEX SmallTableCI ON SmallTable (c1);
GO

INSERT INTO SmallTable VALUES (1, 1);INSERT INTO SmallTable VALUES (2,2);
GO

Далее я включу READ_COMMITTED_SNAPSHOT и перестрою индекс, чтобы проверить, сработает ли версионирование на уровне выражения:

ALTER DATABASE SItest SET READ_COMMITTED_SNAPSHOT ON;
GO

ALTER INDEX SmallTableCI ON SmallTable REBUILD;
GO

Теперь посмотрим на страницу данных, где лежат две записи, чтобы выяснить, есть ли какие-либо сведения о версионировании (вывод немного укорочен для краткости):

DBCC IND (SItest, SmallTable, 1);
GO

DBCC TRACEON (3604); — remember this makes the output go to the consoleDBCC PAGE (SItest, 1, 153, 3);
GO
PageFID PagePID     IAMFID IAMPID      ObjectID    IndexID
——- ———– —— ———– ———– ———–
1       154         NULL   NULL        2073058421  1
1       153         1      154         2073058421  1


(2 row(s) affected)


DBCC execution completed. If DBCC printed error messages, contact your system administrator.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.


PAGE: (1:153)

<SNIP SNIP SNIP>

Slot 0 Offset 0x60 Length 15

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP
Memory Dump @0x6209C060

00000000:   10000c00 01000000 01000000 0300f9 ……………
UNIQUIFIER = [NULL]

Slot 0 Column 1 Offset 0x4 Length 4

c1 = 1

Slot 0 Column 2 Offset 0x8 Length 4

c2 = 1

Slot 1 Offset 0x6f Length 15

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP
Memory Dump @0x6209C06F

00000000:   10000c00 02000000 02000000 0300f9 ……………
UNIQUIFIER = [NULL]

Slot 1 Column 1 Offset 0x4 Length 4

c1 = 2

Slot 1 Column 2 Offset 0x8 Length 4

c2 = 2

DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Нет — обе записи выглядят обычно. Для полноты картины попробуем версионирование на уровне транзакции и затем перестроение:

ALTER DATABASE SItest SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

ALTER INDEX SmallTableCI ON SmallTable REBUILD;
GO

DBCC IND (SItest, SmallTable, 1);
GO

DBCC PAGE (SItest, 1, 143, 3); — page changed when we rebuilt the indexGO
PageFID PagePID     IAMFID IAMPID      ObjectID    IndexID
——- ———– —— ———– ———– ———–
1       152         NULL   NULL        2073058421  1
1       143         1      152         2073058421  1


(2 row(s) affected)


DBCC execution completed. If DBCC printed error messages, contact your system administrator.

PAGE: (1:143)

<SNIP SNIP SNIP>

Slot 0 Offset 0x60 Length 15

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP
Memory Dump @0x6209C060

00000000:   10000c00 01000000 01000000 0300f9 ……………
UNIQUIFIER = [NULL]

Slot 0 Column 1 Offset 0x4 Length 4

c1 = 1

Slot 0 Column 2 Offset 0x8 Length 4

c2 = 1

Slot 1 Offset 0x6f Length 15

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP
Memory Dump @0x6209C06F

00000000:   10000c00 02000000 02000000 0300f9 ……………
UNIQUIFIER = [NULL]

Slot 1 Column 1 Offset 0x4 Length 4

c1 = 2

Slot 1 Column 2 Offset 0x8 Length 4

c2 = 2

DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Снова нет — ничего. Теперь я принудительно спровоцирую операцию версионирования, и мы должны увидеть теги. Любое обновление таблицы приводит к созданию версионированных записей. В данном случае я начну явную транзакцию и выполню несколько обновлений, а исходные значения посмотрим из другого окна запроса. Сначала — обновления:

BEGIN TRAN;
GO

UPDATE SmallTable SET c1 = 4;
GO

А в другом окне:

SELECT * FROM smalltable;
GO


c1          c2
———– ———–
1           1
2           2


(2 row(s) affected)

Отлично — исходные значения по‑прежнему видны. Посмотрим сведения о версионировании на странице данных (вывод снова укорочен):

DBCC PAGE (SItest, 1, 143, 3);
GO

PAGE: (1:143)

<SNIP SNIP SNIP>

Slot 0 Offset 0x7e Length 29

Record Type = GHOST_DATA_RECORD      Record Attributes =  NULL_BITMAP VERSIONING_INFO

Memory Dump @0x61CEC07E

00000000:   5c000c00 01000000 01000000 0300f9e0 \……………
00000010:   00000001 00000057 03000000 00       …….W…..

**Version Infomation =
 Transaction Timestamp: 855
 Version Pointer: (file 1 page 224 slot 0)**

UNIQUIFIER = [NULL]

Slot 0 Column 1 Offset 0x4 Length 4

c1 = 1

Slot 0 Column 2 Offset 0x8 Length 4

c2 = 1

Slot 1 Offset 0xb8 Length 29

Record Type = GHOST_DATA_RECORD      Record Attributes =  NULL_BITMAP **VERSIONING_INFO**

Memory Dump @0x61CEC0B8

00000000:   5c000c00 02000000 02000000 0300f9e0 \……………
00000010:   00000001 00010057 03000000 00       …….W…..

**Version Infomation =
 Transaction Timestamp: 855
 Version Pointer: (file 1 page 224 slot 1)**

UNIQUIFIER = [NULL]

Slot 1 Column 1 Offset 0x4 Length 4

c1 = 2

Slot 1 Column 2 Offset 0x8 Length 4

c2 = 2

Slot 2 Offset 0x9b Length 29

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VERSIONING_INFO

Memory Dump @0x61CEC09B

00000000:   50000c00 04000000 01000000 0300f800 P……………
00000010:   00000000 00000057 03000000 00       …….W…..

 Version Information =
 Transaction Timestamp: 855
 Version Pointer: Null

UNIQUIFIER = [NULL]

Slot 2 Column 1 Offset 0x4 Length 4

c1 = 4

Slot 2 Column 2 Offset 0x8 Length 4

c2 = 1

Slot 3 Offset 0xd5 Length 37

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS VERSIONING_INFO

Memory Dump @0x61CEC0D5

00000000:   70000c00 04000000 02000000 0300f801 p……………
00000010:   00170001 00000000 00000000 00000057 ……………W
00000020:   03000000 00                         …..

 Version Information =
 Transaction Timestamp: 855
 Version Pointer: Null

 
Slot 3 Column 0 Offset 0x13 Length 4

UNIQUIFIER = 1

Slot 3 Column 1 Offset 0x4 Length 4

c1 = 4

Slot 3 Column 2 Offset 0x8 Length 4

c2 = 2

DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Я выделил части, относящиеся к версионированию, полужирным. Обратите внимание, что старые записи тоже превратились в фантомные (ghost). Вторая запись теперь помечена как имеющая столбцы переменной длины. Это потому, что я обновил обе записи до одного и того же значения кластерного ключа, и второй записи теперь требуется «уникализатор» (uniquifier) — он хранится как столбец переменной длины.

Итак, исходное утверждение — миф: строки получают сведения о версионировании только тогда, когда это действительно нужно для поддержки операции версионирования.



Комментариев нет:

Отправить комментарий