All the BizTalk databases which is being backed up by the ‘Backup BizTalk Server’ job, so all databases with the exception of the BAM Star Schema database (BAMStarSchema), has one table called “MarkLog”.

These tables are holding all the transaction marks (they are actually timestamps in a string format), set to a specific database, created by the 3rd step (MarkAndBackUpLog) of the ‘Backup BizTalk Server’ job. This step, MarkAndBackupLog, is responsible for marking the logs for backup, and then backing them up. So each time this step runs, by default every 15 minutes, a string is stored in that table with the following naming convention:

  • Log_<yyyy>_<MM>_<dd>_<HH>_<mm>_<ss>_<fff>

Where:

  • Log”: Constant string
  • yyyy: The year as a four-digit number.
  • MM: The month, from 01 through 12
  • dd: The day of the month, from 01 through 31.
  • HH: The hour, using a 24-hour clock from 00 to 23.
  • mm: The minute, from 00 through 59.
  • ss: The second, from 00 through 59.
  • fff: The milliseconds in a date and time value.

Again, these marks are timestamps in which the Log backups were set to be made. Example:

  • BTS_2014_05_06_14_15_01_327

Unfortunately, BizTalk has no out-of-the-box possibilities to clean up these tables. And the normal procedure is to run the terminator tool to clean it up.

Terminator Tool Purge MarkLogs

BizTalk Terminator is an excellent tool that allows for common BizTalk problems to be addressed by scripts provided by the BizTalk Team but needs to be used carefully and by users who know what they are doing.

Although most of the time this is an extremely useful tool and our friend, in this particular operation/situation using this tool it’s not really the best option for two reasons:

  • Using this tool means that we need to stop our environment, i.e., downtime in our integration platform.
  • And if we look at the description of this “PURGE Marklog table” task it says that this operation calls a SQL script that cleans up everything in Marklog table – and maybe this is not the best practices!

I spoke to my dear friend, and one of the best BizTalk Administrator that I know, Tord Glad Nordahl to discuss and know what should be the best practice to maintain these tables:

  • Is this information (timestamps) useful for BizTalk Administrators?
  • Should I clean all the data inside these tables or should I maintain a history?
  • Is safe to clean this information in runtime?

Here are some of the questions that we discussed.

Is this information (timestamps) useful for BizTalk Administrators? Should I clean all the data inside these tables or should I maintain a history?

For the same reason that we maintain a Backup history in the Adm_BackupHistory table controlled by the step “Clear Backup History” of the ‘Backup BizTalk Server’ job. This information is important for example to keep an eye on the backup/log shipping history records to see whether the backup is working correctly and data/logs are restored correctly in the standby environment. The information on the MarkLog tables is also useful for the BizTalk Administration team!

So as long as the MarkLog tables have the same info (data from the same dates) as the backup job days to keep you can safely delete the rest of the information.

As best practices: you should respect the @DaysToKeep parameter that you specify in the “Clear Backup History” step of the ‘Backup BizTalk Server’ job.

And this is why that in my opinion, you shouldn’t use the Terminator tool to perform this operation!

Is safe to clean this information in runtime?

The rows in the Marklog table are not “required” and can be cleaned whenever you want as long the BizTalk Backup Job is not running.

Cleaning MarkLog Tables According to Some of the Best Practices

So the main challenge is how can we safely delete and maintain a history of all MarkLog tables according to some of the best practices described earlier?

My first approach was creating a new job that according to a scheduler would run a stored procedure to delete all the unnecessary information on those tables but I realized I could have two problems with this approach:

  • I need to be sure that BizTalk Backup Job wasn’t running performing the backups;
  • And I didn’t want to have to places to define the @DaysToKeep and I didn’t want to make unnecessary joins or additional selects

I was trying to find an approach for this operation to be carried out in an easy way and as fast as possible.

So I end up recreating sp_DeleteBackupHistory (that is configured is the Backup BizTalk Server (BizTalkMgmtDb) job in the last step) with a different name sp_DeleteBackupHistoryAndMarkLogsHistory and configure the job to run this step:

CREATE PROCEDURE [dbo].[sp_DeleteBackupHistoryAndMarkLogsHistory] @DaysToKeep smallint = null, @UseLocalTime bit = 0
AS
 BEGIN
 set nocount on
 IF @DaysToKeep IS NULL OR @DaysToKeep &lt;= 0
 RETURN
 /*
 Only delete full sets
 If a set spans a day such that some items fall into the deleted group and the other don't don't delete the set

 Delete history only if history of full Backup exists at a later point of time
 why: history of full backup is used in sp_BackupAllFull_Schedule to check if full backup of databases is required or not.
 If history of full backup is not present, job will take a full backup irrespective of other options (frequency, Backup hour)
 */

 declare @PurgeDateTime datetime
 if (@UseLocalTime = 0)
 set @PurgeDateTime = DATEADD(dd, -@DaysToKeep, GETUTCDATE())
 else
 set @PurgeDateTime = DATEADD(dd, -@DaysToKeep, GETDATE())

 DELETE [dbo].[adm_BackupHistory]
 FROM [dbo].[adm_BackupHistory] [h1]
 WHERE  [BackupDateTime] &lt; @PurgeDateTime
 AND [BackupSetId] NOT IN ( SELECT [BackupSetId] FROM [dbo].[adm_BackupHistory] [h2] WHERE [h2].[BackupSetId] = [h1].[BackupSetId] AND [h2].[BackupDateTime] &gt;= @PurgeDateTime)
 AND EXISTS( SELECT TOP 1 1 FROM [dbo].[adm_BackupHistory] [h2] WHERE [h2].[BackupSetId] &gt; [h1].[BackupSetId] AND [h2].[BackupType] = 'db')

 /****** Delete MarkLog History from BAMAlertsApplication database ******/
 DELETE FROM [BAMAlertsApplication].[dbo].[MarkLog]
    WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from BAMArchive database* *****/
 DELETE FROM [BAMArchive].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from BAMPrimaryImport database ******/
 DELETE FROM [BAMPrimaryImport].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from BizTalkDTADb database ******/
 DELETE FROM [BizTalkDTADb].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from BizTalkMgmtDb database ******/
 DELETE FROM [BizTalkMgmtDb].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from BizTalkMsgBoxDb database ******/
 DELETE FROM [BizTalkMsgBoxDb].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from BizTalkRuleEngineDb database ******/
 DELETE FROM [BizTalkRuleEngineDb].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep

 /****** Delete MarkLog History from SSODB database ******/
 DELETE FROM [SSODB].[dbo].[MarkLog]
 WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),'_',''), GETDATE()) &gt; @DaysToKeep
 END

Steps required to install/configure

  • Create the sp_DeleteBackupHistoryAndMarkLogsHistory stored procedure described earlier
  • You need to adjust the SQL Script to your environment because some environment may not have all features installed, for example, Business Rules and in this case, BizTalkRuleEngineDb database will not exist.
  • Change and configure the 4th step of the ‘Backup BizTalk Server’ job – “Clear Backup History” to call this new stored procedure
sp_DeleteBackupHistoryAndMarkLogsHistory

Note: Do not change or delete the “sp_DeleteBackupHistory”!

Special thanks to Tord Glad Nordahl for reviewing and all the feedback, and to my friends at DevScope Rui Romano and Pedro Sousa for helping me develop this SQL Query.

Hope you find it useful

Download

THIS SQL SCRIPT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.

You can download BizTalk Server: Cleaning MarkLog Tables According to Some of the Best Practices from GitHub here:

Author: Sandro Pereira

Sandro Pereira lives in Portugal and works as a consultant at DevScope. In the past years, he has been working on implementing Integration scenarios both on-premises and cloud for various clients, each with different scenarios from a technical point of view, size, and criticality, using Microsoft Azure, Microsoft BizTalk Server and different technologies like AS2, EDI, RosettaNet, SAP, TIBCO etc. He is a regular blogger, international speaker, and technical reviewer of several BizTalk books all focused on Integration. He is also the author of the book “BizTalk Mapping Patterns & Best Practices”. He has been awarded MVP since 2011 for his contributions to the integration community.

2 thoughts on “Managing and cleaning BizTalk Server MarkLog database tables according to some Best Practices”

  1. Hi ,
    using your script sp_DeleteBackupHistoryAndFiles from http://sandroaspbiztalkblog.wordpress.com/2013/05/26/biztalk-2013-installation-and-configuration-configure-biztalk-server-sql-jobs-part-15/
    as a base add adding the code below I have a solution that worked out very well. By using the view admv_BackupDatabases to get server and databases names the script becomes more dynamic and it works no matter how
    your server and biztalk database configuration looks like. I like the idea of having all the clean up done in the same script as the actual backup is done as this makes sure that backup files and history is only
    deleted when a backup is successful. What I don’t like is the use of xp_cmdshell and I would love to see an elegant solution on how to delete files without using xp_cmdshell.

    /* Cleaning MarkLog Tables if entry is older than @DaysToKeep x 10
    */

    DECLARE @cmd2 nvarchar(MAX)
    DECLARE BackupDatabases CURSOR
    FOR SELECT ‘[‘+ServerName+’].[‘+DatabaseName+’]’ FROM admv_BackupDatabases

    OPEN BackupDatabases
    FETCH NEXT FROM BackupDatabases INTO @cmd2
    WHILE (@@fetch_status -1)
    BEGIN
    IF (@@fetch_status -2)
    BEGIN
    SET @cmd2 = ‘DELETE FROM ‘+@cmd2 + ‘.[dbo].[MarkLog] WHERE DATEDIFF(day, REPLACE(SUBSTRING([MarkName],5,10),”_”,””), GETDATE()) >’ + Convert(varchar,@DaysToKeep) + ‘0’
    EXEC sp_executesql @cmd2
    END
    FETCH NEXT FROM BackupDatabases INTO @cmd2
    END
    CLOSE BackupDatabases
    DEALLOCATE BackupDatabases

    Best Regards,
    Jimmy H

  2. Hi!
    The sp is not working in our environment where we are using AG, our Marklog tables has never been cleaned up and I think it is because it reads the servernames from the view admv_BackupDatabases and in that view the servernames are the AG names. I can clean up the tables manually by writing USE [Datatabase] and the tablenames. How can we change the sp to work in the AG?

Leave a Reply

Your email address will not be published. Required fields are marked *

turbo360

Back to Top