Log records of update statement

Compared to insert and delete statement, the update statement creates more log records, even more than you expected.

I’m going to use fn_dblog to show you HOW sql server create the log records

Let’s populate some data here

create database dbtest
go
use dbtest
go
create table table1(c1 char(10),c2 varchar(10),c3 varchar(10),c4 varchar(10))
go
insert table1 values(REPLICATE('a',10),REPLICATE('b',10),REPLICATE('c',10),REPLICATE('d',10))
go
dbcc ind(dbtest,table1,1)----the pate id is 1:328
go

Here is the content of the row

dbcc traceon(3604)
go
dbcc page(dbtest,1,328,1)
Slot 0, Offset 0x60, Length 47, DumpStyle BYTE

Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 47

Memory Dump @0x000000192D4F8060

0000000000000000:   10002c00 61616161 61616161 61616262 62626262  ..,.aaaaaaaaaabbbbbb
0000000000000014:   62626262 63636363 63636363 63636464 64646464  bbbbccccccccccdddddd
0000000000000028:   64646464 040000                               dddd...

Let’s update the column c1 and c2

begin tran updateTest1
update table1 set c1=REPLICATE('e',10),c2=REPLICATE('f',10)
commit
go
select  Operation,  [Transaction name],[page id], [RowLog Contents 0],[RowLog Contents 1]
from sys.fn_dblog(null,null) where [transaction id] in (select [transaction id]from sys.fn_dblog(null,null) where [Transaction name]='updateTest1')

Here is the result returned by fn_dblog

Operation                       Transaction name                  page id        RowLog Contents 0                             RowLog Contents 1                          
------------------------------- --------------------------------- -------------- --------------------------------------------- -------------------------------------------
LOP_BEGIN_XACT                  updateTest1                       NULL           NULL                                          NULL                                       
LOP_MODIFY_ROW                  NULL                              0001:00000148  0x6161616161616161616162626262626262626262    0x6565656565656565656566666666666666666666 
LOP_COMMIT_XACT                 NULL                              NULL           NULL                                          NULL                                       

For update statement, [RowLog Contents 0] stands for ‘before image’, the data before the update is executed. While the [RowLog Contents 1] stands for ‘after image’ the data after update is executed.

The ‘Before image’ has the content of c1 +c2 before the update is executed , and ‘after image’ has the content of new c1+c2 . This is what I expected.

The content of row after the update is:

Slot 0, Offset 0x8f, Length 47, DumpStyle BYTE

Record Type = PRIMARY_RECORD        Record Attributes =  NULL_BITMAP    Record Size = 47

Memory Dump @0x000000192D4F808F

0000000000000000:   10002c00 65656565 65656565 65656666 66666666  ..,.eeeeeeeeeeffffff
0000000000000014:   66666666 63636363 63636363 63636464 64646464  ffffccccccccccdddddd
0000000000000028:   64646464 040000                               dddd...

But here is something shocked me when I saw it first time. I’m trying to update c1 and c3.

begin tran updateTest2
update table1 set c1=REPLICATE('g',10),c3=REPLICATE('h',10)
commit
go
select  Operation,  [Transaction name],[page id],[RowLog Contents 0],[RowLog Contents 1]
from sys.fn_dblog(null,null) where [transaction id] in (select [transaction id]from sys.fn_dblog(null,null) where [Transaction name]='updateTest2')

Here is what I got from the fn_dblog

Operation        Transaction name   page id        RowLog Contents 0                                               RowLog Contents 1                                              
---------------- ------------------ -------------- --------------------------------------------------------------- ---------------------------------------------------------------
LOP_BEGIN_XACT   updateTest2        NULL           NULL                                                            NULL                                                           
LOP_MODIFY_ROW   NULL               0001:00000148  0x656565656565656565656666666666666666666663636363636363636363  0x676767676767676767676666666666666666666668686868686868686868 
LOP_COMMIT_XACT  NULL               NULL           NULL                                                            NULL                                                           

The ‘Before Image’ does not only have the data of c1 and c3, but also has the data of c2. The ‘After image’ follows the same pattern.

The update query does not update the c2, which is between the c1 and c3, but the log records actually have the c2 data, it causes the log records greater than expected.

The more columns the table has, the more log records will be created.. You may try to update the first column and the last column against a table has 10 columns to test…(Please note, you may need to review the ‘RowLog Contents x’ for before image and after image)

Leave a comment