Triggers and row versioning information
Under what circumstances will table triggers cause 14 bytes to be added to the end of the row for row versioning?
The "Space Used in Data Rows" section on this page clearly states "Each database row may use up to 14 bytes at the end of the row for row versioning information ... These 14 bytes are added the first time the row is modified, or when a new row is inserted, under any of these conditions ... The table has a trigger."
This didn't happen in my test (script below). When looking at the data page I don't see any of the versioning info that appears under snapshot isolation. Am I safe in assuming that the rows on data pages will never get bloated by this 14 bytes just because a trigger is on the table? If not when will this occur?
CREATE DATABASE D2
GO
ALTER DATABASE D2 SET ALLOW_SNAPSHOT_ISOLATION OFF
USE D2;
GO
CREATE TABLE T1
(
F1 IN开发者_C百科T IDENTITY(1,1) PRIMARY KEY,
F2 INT,
V1 VARCHAR(100)
)
INSERT INTO T1
SELECT TOP 80 ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS F2,
REPLICATE(CHAR((ROW_NUMBER() OVER (ORDER BY (SELECT 0) -1) % 26) + ASCII('A')),100) AS V1
FROM sys.all_columns
GO
CREATE TRIGGER TR
ON T1
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM inserted
END
GO
UPDATE T1 SET F2=F2+1
GO
DECLARE @DBCCPAGE nvarchar(100)
SELECT TOP 1 @DBCCPAGE = 'DBCC PAGE(''D2'',' + CAST(file_id AS VARCHAR) + ',' + CAST(page_id AS VARCHAR) + ',3)'
FROM T1
CROSS APPLY sys.fn_PhysLocCracker(%%physloc%%)
DBCC TRACEON(3604)
EXEC (@DBCCPAGE)
GO
Paul Randal has a handy article called: "Inside the Storage Engine: When do versioning tags get added?". The clue is in the title :-)
This is all explained in this blog post.
The reason why I did not see any versioning pointers in my original test is because of the table definition.
There is a performance optimization that can avoid adding row versioning information, but only if the table cannot generate
ROW_OVERFLOW
orLOB
allocation units. This means that the definition of the table must not allow for LOBs or for the possibility of variable length columns moving off row. The actual size of the data stored is immaterial – it is the potential size that matters.
If I change the table definition to
CREATE TABLE T1
(
F1 INT IDENTITY(1,1) PRIMARY KEY,
F2 INT,
V1 VARCHAR(1000),
V2 VARCHAR(8000) NULL
)
So that potentially it might not all fit in row then I do see version pointers in the DBCC
results. e.g. as below.
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS VERSIONING_INFO
Record Size = 133
Memory Dump @0x63A4CC92
00000000: 70000c00 03000000 04000000 04004801 †p.............H.
00000010: 00770044 44444444 44444444 44444444 †.w.DDDDDDDDDDDDD
00000020: 44444444 44444444 44444444 44444444 †DDDDDDDDDDDDDDDD
00000030: 44444444 44444444 44444444 44444444 †DDDDDDDDDDDDDDDD
00000040: 44444444 44444444 44444444 44444444 †DDDDDDDDDDDDDDDD
00000050: 44444444 44444444 44444444 44444444 †DDDDDDDDDDDDDDDD
00000060: 44444444 44444444 44444444 44444444 †DDDDDDDDDDDDDDDD
00000070: 44444444 444444c8 7b000001 000500b8 †DDDDDDDÈ{......¸
00000080: 00000000 00††††††††††††††††††††††††††.....
Version Information =
Transaction Timestamp: 184
Version Pointer: (file 1 page 31688 currentSlotId 5)
精彩评论