
{"id":7044,"date":"2022-04-28T16:32:15","date_gmt":"2022-04-28T16:32:15","guid":{"rendered":"https:\/\/rax-stg-wp-aws.com\/blogs\/truncate-and-delete-operation-auditing-in-mssql-server\/"},"modified":"2026-11-03T19:27:41","modified_gmt":"2026-11-03T19:27:41","slug":"truncate-and-delete-operation-auditing-in-mssql-server","status":"publish","type":"blogs","link":"https:\/\/www.rackspace.com\/de\/blogs\/truncate-and-delete-operation-auditing-in-mssql-server\/","title":{"rendered":"Truncate and delete operation auditing in MSSQL Server"},"content":{"rendered":"<p>This blog discusses the steps to determine the user responsible for truncating and removing data from tables on the MSSQL server, and identify the entity responsible.&nbsp;<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<\/p>\n<p>For example:&nbsp;<br \/>\nWhen was the table truncated, and when was the data removed from the table?<br \/>\nWho truncated the table and removed data from the table?<\/p>\n<p><strong>Reason to collect this information<\/strong><br \/>\nThis is to see if someone deleted the data on purpose or by accident, so we can track down the individual and take preventative action. We received a few requests from customers looking for this information.<br \/>\nWhen we know the exact time of the data purge operation then we can easily recover the data with a stop-at clause during the log backup operation.<\/p>\n<p><strong>Summary of the problem<\/strong><\/p>\n<p>The following sections describe four key principles of GitOps:<\/p>\n<p>Between 5 p.m. and 7 p.m. on January 5, 2020, the &#8220;dump truncate&#8221; table was truncated and the data from the &#8220;dump delete&#8221; table was removed from the &#8220;truncate test&#8221; DB. The probable questions that need to be addressed include:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>&nbsp;You need to figure out what the problem is.<\/li>\n<li>&nbsp;Who removed the data from the \u201cdump_delete\u201d table?<\/li>\n<li>&nbsp;How many rows from the &#8220;dump delete&#8221; table were deleted?<\/li>\n<li>&nbsp;Who truncated the \u201cdump_truncate\u201d table?<\/li>\n<li>&nbsp;When were these tables truncated and deleted?<\/li>\n<li>&nbsp;On the server, the current backup schedule is as follows:<\/li>\n<li>&nbsp;Every week on Sunday, full backups are taken.<\/li>\n<li>&nbsp;Every day at 1 p.m., diff backup<\/li>\n<li>&nbsp;Backups of logs are generated every 15 minutes.<\/li>\n<\/ul>\n<p><strong>Prerequisites:<\/strong><\/p>\n<ul>\n<li><em>DB should be in full recovery mode.<\/em><\/li>\n<li><em>Full, diff and log backups should be available.<\/em><\/li>\n<\/ul>\n<p><strong>Approach at a high level<\/strong><\/p>\n<p>&nbsp;<\/p>\n<ol>\n<li>Identify which log backup holds delete and truncate operations.<\/li>\n<li>Identify details of truncate and delete operations using log backup.<\/li>\n<\/ol>\n<p><strong>Determine which log backup holds the delete and truncate operations:<\/strong><\/p>\n<p><strong>NOTE: We performed these steps by creating a new copy of the DB.<\/strong><\/p>\n<ol>\n<li>Restore 2nd Jan Sunday full backup with standby mode.<\/li>\n<li>Restore 5th Jan diff backup with standby mode3)&nbsp;&nbsp; &nbsp;Restore log backup with standby mode. Check the table count after each log restore to see which log backup holds the truncate and delete operation logs.<\/li>\n<\/ol>\n<p>When we restored the log backup from 6 PM, the &#8220;dump truncate&#8221; table was empty, and entries from the &#8220;dump delete&#8221; table were missing. As a result, it denotes:<\/p>\n<p>Between 5:45 PM and 6 PM, the &#8220;dump truncate&#8221; table was truncated, and data from the &#8220;dump delete&#8221; table was wiped simultaneously.<\/p>\n<p>You need to run the following restore commands:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture1.PNG\" alt=\"MSSQL 1 \" \/><\/p>\n<p><strong>Identify details of truncate and delete operations using log backup:<\/strong><\/p>\n<p>Step 1: Collect transaction IDs for all truncate and delete operations that occurred between 5:45 and 6 p.m.<\/p>\n<p><strong>Query:&nbsp;<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture2.PNG\" alt=\"MSSQL 2\" \/><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture3_0.png\" alt=\"MSSQL 3\" \/><\/p>\n<p>We discovered that two operations, delete and truncate, were executed at 5:50 PM, and that these operations were performed by login RP Dev.<\/p>\n<p>Step 2: Find the table names that are associated to the transaction id.<\/p>\n<p><em>To get information on the delete operation, follow the steps below<\/em><\/p>\n<p>I) Determine the delete operation&#8217;s object ID and partition ID.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture4.PNG\" alt=\"MSSQL 4\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture5_0.png\" alt=\"MSSQL 5 \" \/><\/p>\n<p>&nbsp;From this output, we can deduce the following information:<br \/>\n<em><strong>Description and Transaction Name columns: Delete operation was performed<\/strong><\/em><br \/>\n&nbsp;<\/p>\n<ul>\n<li>Begin Time: Delete operation was started at 2022\/01\/05 17:50:22:493<\/li>\n<li>Login_Name: RP_DEV had run the delete operation.<\/li>\n<li>Lock Information: Each row beginning with the prefix &#8220;HoBt&#8221; represents one row deletion, for a total of 7 rows.<\/li>\n<li>Object ID associated with the table from which data was removed.<\/li>\n<li>Partition Id: Partition id of the object from where data was deleted&nbsp;<\/li>\n<\/ul>\n<p><strong>II) Locate a table that contains the object ID and partition ID.&nbsp;<\/strong><\/p>\n<p>Query:<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture6.PNG\" alt=\"MSSQL 6\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture7_0.png\" alt=\"MSSQL 7 \" \/><\/p>\n<p>&nbsp;<br \/>\nNow we can deduce that data from &#8220;dump delete&#8221; was removed by RP DEV user at 5:50 PM under the transaction ID &#8216;0000:00016a96&#8217; and that a total of 7 rows were deleted.<\/p>\n<p><strong>To get information on the truncate operation, follow the steps below:<\/strong><\/p>\n<p><em>I) Determine the Truncate operation&#8217;s object ID and partition ID<\/em><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture8.PNG\" alt=\"MSSQL8\" \/><\/p>\n<p>&nbsp;<strong>OUTPUT<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture9.png\" alt=\"MSSQL 9\" \/><\/p>\n<p>Now we can deduce that data from &#8220;dump delete&#8221; was removed by RP DEV user at 5:50 PM under the transaction ID &#8216;0000:00016a96&#8217; and that a total of 7 rows were deleted.<\/p>\n<p><strong>To get information on the truncate operation, follow the steps below:&nbsp;<\/strong><\/p>\n<p><strong>I) <\/strong><em>Determine the Truncate operation&#8217;s object ID and partition ID.<\/em><\/p>\n<p><strong>Query:<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture10.PNG\" alt=\"MSSQL 10\" \/><\/p>\n<p><strong>Output<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture11.png\" alt=\"MSSQL 11\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\nThe output of the truncate operation differs slightly from that of the delete operation.<\/p>\n<p><strong>Partition ID column:<\/strong> It is not displaying the correct partition ID. You can find this information in the description column. Partition ID is highlighted. Partition IDs are 72057594043564032 and 72057594043629568<\/p>\n<p><strong>Lock Description: <\/strong>Always <em>SCH_M_OBJECT row&nbsp;<\/em>in Lock Description shows the correct Object ID. Object ID is: 885578193<\/p>\n<p>Locate a table that contains the object ID and partition ID&nbsp;<\/p>\n<p><strong>Query:&nbsp;<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture12.PNG\" alt=\"MSSQL 12\" \/><\/p>\n<p><strong>Output<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26213-body-Picture13.png\" alt=\"MSSQL 13\" \/><\/p>\n<p>We can now establish that data from &#8220;dump truncate&#8221; was truncated at 5:50 PM by RP_DEV user under the transaction ID&#8217;0000:00016a95&#8242;.<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>It is useful to know who performed the truncate and delete operation on data to avoid this from happening again when auditing is not already enabled.&nbsp;<br \/>\nIn case of a delete operation, the business will have an idea of how many rows are removed.&nbsp;<br \/>\nTo have the exact time of recovery will be very helpful in recovering the data.<br \/>\nFurther third-party tools like ApexSQL Log and ApexSQL Recover can also be used to recover the data.&nbsp;<\/p>\n<p>Refer to this <a href=\"https:\/\/knowledgebase.apexsql.com\/recovery-features-comparison-apexsqllog-vs-apexsqlrecover\/\">link<\/a> to learn more about these tools.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Truncate and delete operation auditing in MSSQL Server| Rackspace Technology<\/p>\n","protected":false},"author":2,"featured_media":7046,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","format":"standard","meta":{"content-type":"","nid":"26213","content_type":"blog","created_by":"10130","authored_on":"2023-11-04T16:32:15+00:00","field_article_industries":"","tag_category":"Technical","field_blog_author_text":"by Tarun Kumar, Software Developer, Rackspace Technology","seo_description":"Identify the user responsible for truncating and removing data in MSSQL Server tables. Gain insights into actions and timestamps.\r\n","field_featured_image":"","insights_image":"\/wp-content\/uploads\/2026\/blog_technical_images\/26213-insights_image-database-technical-blog-2-insights.jpg","field_partners":"","rxt_platforms":"Microsoft SQL","product":"","publisheddate":"2022-04-28T16:32:15","rxt_solutions":"","opengraph_tag":"","x_tag":"","teaser_flag":"Technical Blog","seo_titile":"Truncate and Delete in MSSQL Server | Rackspace Technology","field_topics":"","field_slug":"truncate-and-delete-operation-auditing-in-mssql-server","footnotes":""},"categories":[178],"tags":[204],"class_list":["post-7044","blogs","type-blogs","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-technical"],"_links":{"self":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs\/7044","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs"}],"about":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/types\/blogs"}],"author":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/comments?post=7044"}],"version-history":[{"count":2,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs\/7044\/revisions"}],"predecessor-version":[{"id":8787,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/blogs\/7044\/revisions\/8787"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/media\/7046"}],"wp:attachment":[{"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/media?parent=7044"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/categories?post=7044"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rackspace.com\/de\/wp-json\/wp\/v2\/tags?post=7044"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}