【问题标题】:Triggers and row versioning information触发器和行版本信息
【发布时间】:2011-07-03 15:28:25
【问题描述】:

表触发器在什么情况下会导致行尾增加14字节进行行版本控制?

“数据行中使用的空间”部分on this page 明确指出“每个数据库行最多可以在行的末尾使用 14 个字节用于行版本控制信息……这 14 个字节是第一次添加该行被修改,或插入新行时,在任何这些条件下... 表有触发器。"

这在我的测试中没有发生(下面的脚本)。查看数据页面时,我看不到快照隔离下出现的任何版本信息。我是否可以安全地假设数据页上的行永远不会因为触发器在表上而被这 14 个字节膨胀?如果没有,什么时候会发生?

CREATE DATABASE D2

GO

ALTER DATABASE D2 SET ALLOW_SNAPSHOT_ISOLATION OFF

USE D2;

GO

CREATE TABLE T1
(
F1 INT 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

【问题讨论】:

  • 这 14 个字节没有被追加到行,因为 ALLOW_SNAPSHOT_ISOLATION 设置为 OFF 你不需要打开它来追加行版本控制数据吗?
  • @Barry - 似乎是这样。我只是想弄清楚我的问题中的链接在说什么。不知道为什么/何时有触发器会有所作为。在我读过的一本 SQL Server 书中也提到了这一点,但没有额外解释,我最好的猜测是它只是在谈论 inserted / deleted 伪表,但不确定为什么这值得在 Space Used in Data Rows 部分中添加条目.
  • 可能是由于 SQL2K5 中对触发器填充已删除表的方式所做的更改。用于扫描事务日志的触发器,已更改为使用行级版本控制来提高性能。请参阅this article,尤其是标题Additional SQL Server 2005 Features utilizing Row Level Versioning 之后的段落
  • @Barry - 那篇文章没有回答为什么我在测试中看不到任何版本信息的问题。原来这取决于表定义。

标签: sql-server sql-server-2008 triggers


【解决方案1】:

这都解释了in this blog post

我在原始测试中没有看到任何版本控制指针的原因是表定义。

有一个性能优化可以避免添加行 版本信息,但前提是表无法生成 ROW_OVERFLOWLOB 分配单元。这意味着定义 表中的内容不得允许 LOB 或 可变长度列移出行。数据的实际大小 存储是无关紧要的——重要的是潜在的大小。

如果我将表定义更改为

CREATE TABLE T1
(
F1 INT IDENTITY(1,1) PRIMARY KEY,
F2 INT,
V1 VARCHAR(1000),
V2 VARCHAR(8000) NULL
)

因此,它可能不完全适合行,然后我确实在DBCC 结果中看到了版本指针。例如如下。

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)

【讨论】:

    【解决方案2】:

    Paul Randal 有一篇方便的文章,名为:"Inside the Storage Engine: When do versioning tags get added?"。线索在标题中:-)

    【讨论】:

    • 因此您的结论是,在任何情况下,添加触发器都不会将数据页上的行长度增加 14 个字节despite what it says here?。在我看来,他们一定只是在谈论 tempdb 中为 deleted 伪表保留的行吗?
    • 这不是我看过,甚至没有想过的东西。但是,我又读了一遍,在我的大表中,14 个字节对我来说已经很多了。 “有一个触发器”的事实是矫枉过正,当然......
    • 我无法在我的任何测试中实现它,甚至无法想到在悲观的并发下它会有用的任何情况。我怀疑它永远不会发生,但会留下问题,以防有人带着明确说明任何一种方式的东西进来......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-19
    相关资源
    最近更新 更多