• GilaMonster (8/15/2012)


    The question was not, does the update cause any log records to be written to the log. The question was, does the update dirty the page if the update makes no changes. It does not, as I showed with the DMV previously.

    I would not be so sure.

    I changed the script to bring out more info:

    USE [TEST]

    GO

    CREATE TABLE [dbo].[Test](

    [ID] [int] IDENTITY(1,1) NOT NULL,

    [Name] [varchar](100) NULL

    ) ON [PRIMARY]

    insert into Test (Name) Values ('TOM')

    insert into Test (Name) Values ('Andy')

    insert into Test (Name) Values ('Bob')

    insert into Test (Name) Values ('Tim')

    Checkpoint -- all dirty pages to disk, truncate log

    SELECT OBJECT_ID('[dbo].[Test]') ObjID, * FROM TEST

    Checkpoint -- all dirty pages to disk, truncate log

    UPDATE test

    SET name = 'Tom'

    WHERE NAME = 'Tom'

    SELECT [Current LSN] ,

    Operation ,

    Context ,

    [Transaction ID] ,

    AllocUnitId ,

    AllocUnitName ,

    [Checkpoint Begin] ,

    [Num Transactions] ,

    [Checkpoint End] ,

    [Dirty Pages] ,

    [Log Record] FROM fn_dblog(NULL, null)

    Checkpoint -- all dirty pages to disk, truncate log

    SELECT * FROM TEST

    DECLARE @I int

    SET @I = 4

    WHILE @I > 0

    BEGIN

    BEGIN TRANSACTION

    UPDATE test

    SET name = NAME

    WHERE @I%2 = 0 OR name <> NAME

    EXEC sp_lock

    COMMIT

    SELECT [Current LSN] ,

    Operation ,

    Context ,

    [Transaction ID] ,

    AllocUnitId ,

    AllocUnitName ,

    [Checkpoint Begin] ,

    [Num Transactions] ,

    [Checkpoint End] ,

    [Dirty Pages] ,

    [Log Record] FROM fn_dblog(NULL, null)

    Checkpoint -- all dirty pages to disk, truncate log

    SET @I = @I - 1

    END

    GO

    Please run the code with Execution Plan recorded.

    1. Define "the same".

    the code

    UPDATE test

    SET name = 'Tom'

    WHERE NAME = 'Tom'

    updates the value with the same, according to the column definition.

    But for some reason SQL Server ignores the collation settings and actually writes the page.

    So, it's not "the same" by data definition, it's "the same" by binary contents of the page(s).

    2. Execution plan shows that "even" updates have 4 records committed to the UPDATE part, and "odd" ones have 0 records committed.

    3. Messages show "(4 row(s) affected)" for "even" updates and "(0 row(s) affected)" for "odd" updates.

    4. SP_LOCK indicates exclusive locks applied on each of 4 records in "even" updates, when condition name <> NAME is not applied.

    To me it means that SQL Server treats those records as perfectly "dirty".

    5. "Even" updates add LOP_BEGIN_XACT and LOP_COMMIT_XACT to the log, when "Odd" ones do not do this.

    But you're right - those updates don't end up in the log file.

    Considering all of the above I can see only one explanation:

    1. UPDATE actually writes to the pages, regardless if the new values are the same or different from the old values.

    But it writes to the pages in memory.

    2. CHECKPOINT compares binary contents of the pages in memory and writes to disk only those ones which have become different after completed transactions.

    When same values are updated there is a record about a committed transaction, so CHECKPOINT has to verify the dirty pages and write to the disk any ones that have been changed. When the query filters out the same values there is no record about a committed transaction, so CHECKPOINT will not even start analysing contents of the pages.

    3. DMV shows the outcome of CHECKPOINT, not UPDATE, therefore the pages updated in memory don't appear there.

    _____________
    Code for TallyGenerator