| 437-991-3573 | Data Engineering Services
Resources Tools
Experts in Microsoft SQL Server on Windows, Linux, Containers | Clusters, Always On, FCI | Migrations, Cloud, Performance

Transactional Replication - Out of Synchronization
by BF (Principal Consultant; Architecture; Engineering)

Replication Monitor - Validate Subscriptions Task

Replication Monitor - Distributor to Subscriber History - Action Message:

Table 'CUSTOMERS' might be out of synchronization. Rowcounts (actual: 135930, expected 135930). Checksum values (actual: 462894789443, expected: 461471150675).

Here we have a situation where the Validation Subscriptions task output is showing the row count is accurate, but there is a difference in the record(s) values.
(Note IF there was a row count difference it is quite easy to figure that issue out by querying the Publisher & Subscriber DB table using left/right outer joins)
To solve the record value difference(s) however takes a comparison of the table records column values themselves - for every record in the table.
That can potentially take a long time if you have a large table. I created a fast method to Hash each record on the Publisher & Subscriber tables
and then run a check on any Hashing differences which would indicate any difference exists in the column values itself.


Ideally the replicated tables are not being updated, by Applications or other Jobs/Processes, at the time of running the below process
because this method uses the primary key value ordering and if records are being inserted/deleted/updated then the check MAY give
false positives.

Step 1: Create a permanent table to hold the source table records hash value. Do this in Publisher & Subscriber DBs.

[TBL] [varchar](150) NULL,
[ROWNO] [int] NULL,
[HashKey] [varbinary](150) NULL,
[InsertedDate] [datetime] NULL


Step 2: Create a Stored Procedure to hash all the table records. Do this in Publisher & Subscriber DBs.

Create Procedure [dbo].[spaHashTableContents_PerObject_v1]
@TblName varchar(150),
@OrderBy varchar(150)

Set NoCount On

exec dbo.spaHashTableContents_PerObject_v1 'CUSTOMER', 'CustomerID'

--select * from TBL_HASH order by rowno asc

Truncate Table dbo.TBL_HASH

Declare @str nvarchar(max)
Select @str = COALESCE(@str + 'convert(varchar(150),', '') + 'isnull(' + + ',0))' + ' + '
from syscolumns t1 inner join sysobjects t2 on =
where = @TblName order by asc
Set @str = LEFT(@str, LEN(@str) - 1)
Set @str = 'SELECT ' + '''' + @TblName + '''' + ' as TBL, Identity(int,1,1) as ROWNO, HASHBYTES(''SHA1'', convert(varchar(150),' + @str + ')
as HASHKEY, getdate() as inserteddate into #TMP from ' + @TblName + ' order by ' + @OrderBy + ' asc' + ''
--Select @str

Set @str = @str + ' Insert into dbo.TBL_HASH Select * from #TMP Truncate Table #TMP'
Exec sp_executesql @str

Step 3: Execute the above abstored procedure in Publisher & Subscriber DBs. This populates each TBL_HASH with the hashing record values.

exec dbo.spaHashTableContents_PerObject_v1 'CUSTOMER', 'CustomerID'

Step 4: Using T-SQL, find any hashing value differences

select * from [PublisherDBName].dbo.TBL_HASH T1
inner join [SubscriberDBName].dbo.TBL_HASH t2
on t1.rowno = t2.rowno
where t1.tbl = 'CUSTOMER'
and t1.hashkey <> t2.hashkey

Notice the HashKey difference!

Step 5: Get the row number (ROWNO) & it's associated Primary Key. The row number is seen in SSMS in the query output / results tab.

Ex. select * from CUSTOMER order by CustomerID asc

At this point you can look at those records manually and see the actual record value differences. Just query the Publisher & Subscriber DBs.

Step 6: Update the Subscriber DB(s)

Now that you have the Primary Key values for the records that have are difference, it is simple to update those on the Subscriber db using an UPDATE statement. Once you execute those updates & execute a Validation Subscriptions task again, the Out Of Synchronization will go away and instead the below message will appear:

Table 'CUSTOMER' passed rowcount (135930) and checksum validation. Checksum is not compared for any text or image columns.

That's it!

The Publisher & Subscriber table is now 100% synchronized. You can take the same approach for any table (article) you have configured for replication.


The benefit to this process is it a very fast method to locate record value differences between a Publisher and Subscriber. The HASHBYTES function executes very fast and
in my case it was hashing a 500MB table in five seconds.

The Geography data type does not work with HASHBYTES. You can filter out that column in the stored procedure syscolumns. Just know that those columns will then require a manual check if necessary.