Bar*_*z X 3 sql-server transaction-log
今天我尝试对 50M+ 行执行更新操作,例如:
UPDATE [table] SET [Column] += 1;
Run Code Online (Sandbox Code Playgroud)
等待 30 分钟后,我看到日志已开始自行填充,再过 30 分钟后,由于日志已满,整个事务回滚。DB 处于简单恢复模式,但这毫无意义,因为这是作为单个事务完成的。SQL Server 本身无法预测它会使用整个日志大小(可以说它为此被锁定了大小),但是我向您提问,亲爱的有经验的 DBA - 您能预测这个大小吗?有没有办法计算这样的估计?
更新:
是的,我了解这个过程,我知道我可以批量处理,我也知道如何让它表现良好。我真正的问题是日志大小将有多大?您将如何计算简单表的更新,例如:
CREATE TABLE [TABL] ([ID] int identity(1,1) PRIMARY KEY CLUSTERED, [X] int not null);
INSERT INTO [TABL] VALUES(1)
GO 1000
UPDATE [TABL]
SET [X] = 2;
Run Code Online (Sandbox Code Playgroud)
在我的测试盒上,操作的更新部分是 6 页大 = 48KB。当我对 10k 行重复相同的操作时,我收到了 144 页的事务日志。对于 100k 行,它是 1314 页,对于 1M,它是 13970 页。这表明我们可以将其视为线性函数(因为我们有额外的页面,无论如何都必须存在,无论我们是否更新任何内容 --> 2-3 页)。
回到开始,我知道我可以在总操作的 5% 上运行一个批处理,检查页面 chenge 内容(如Paul Randal 的博客):
DECLARE @Extent_ID INT;
DECLARE @Size_Total BIGINT = 0;
DECLARE @File_ID INT;
DECLARE @File_Size_Pages INT;
DECLARE @Log_Page_ID INT;
DECLARE @Log_Total BIGINT = 0;
DECLARE @Log_Total_Changed BIGINT;
DECLARE @DBCC_PAGE_String_Log VARCHAR (200);
DECLARE [files] CURSOR FOR
SELECT [file_id], [size]
FROM master.sys.master_files
WHERE [type_desc] = N'ROWS'
AND [state_desc] = N'ONLINE'
AND [database_id] = DB_ID(@DB_Name);
OPEN files;
FETCH NEXT FROM [files] INTO @File_ID, @File_Size_Pages;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Extent_ID = 0;
SET @Size_Total += @File_Size_Pages / 8; --| Convert size in pages to to extents
WHILE (@Extent_ID < @File_Size_Pages)
BEGIN
SELECT @Log_Page_ID = @Extent_ID + 7;
SELECT @DBCC_PAGE_String_Log = 'DBCC PAGE ([' + @DB_Name + '], ' + CAST (@File_ID AS VARCHAR) + ', ' + CAST (@Log_Page_ID AS VARCHAR) + ', 3) WITH TABLERESULTS, NO_INFOMSGS';
TRUNCATE TABLE [msdb].[dbo].[DBCC_Page_Check];
INSERT INTO [msdb].[dbo].[DBCC_Page_Check] EXEC (@DBCC_PAGE_String_Log);
SELECT @Log_Total_Changed = SUM ([msdb].[dbo].[Extent_Change_Checks] ([Field]))
FROM [msdb].[dbo].[DBCC_Page_Check]
WHERE [VALUE] = ' MIN_LOGGED'
AND [ParentObject] LIKE 'ML_MAP%';
SET @Log_Total += @Log_Total_Changed;
SET @Extent_ID += 511232;
END
----------------------------------------------------------------------------------------------------------------------------
FETCH NEXT FROM [files] INTO @File_ID, @File_Size_Pages;
END;
DROP TABLE [msdb].[dbo].[DBCC_Page_Check];
CLOSE [files];
DEALLOCATE [files];
Run Code Online (Sandbox Code Playgroud)
但这仍然需要进行更改(即使有回滚),然后我们才能进行任何估计。再说一次 - 有没有人知道如何比上面的方法更好地估计它 - 预先?