<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Jay's Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/askjay/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/askjay/feed.xml</link>
    <description>[coding, debugging, and troubleshooting with Microsoft Technologies]</description>
    <lastBuildDate>Wed, 24 Feb 2016 10:08:06 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Orphaned Locks  -  Idle Session  -  and XACT_ABORT</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/orphaned-locks-idle-session-and-xact_abort</link>
      <pubDate>Mon, 08 Oct 2012 08:10:21 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/10/08/orphaned-locks-idle-session-and-xact_abort/</guid>
      <description><![CDATA[Sometimes you might see a situation where a session is holding locks, blocking other sessions for an...]]></description>
      <content:encoded><![CDATA[<p>Sometimes you might see a situation where a session is holding locks, blocking other sessions for an extended period of time, but does not have an active request and appears to be Idle.&#160; This can happen in a few different scenarios, but here we’ll outline one scenario and how being sure to use XACT_ABORT can help alleviate this situation.&#160; </p>  <p>For more information on XACT_ABORT, refer to the following:</p>  <blockquote>   <p>SET XACT_ABORT (Transact-SQL)     <br /><a title="https://msdn.microsoft.com/en-us/library/ms188792.aspx" href="https://msdn.microsoft.com/en-us/library/ms188792.aspx">https://msdn.microsoft.com/en-us/library/ms188792.aspx</a></p> </blockquote>  <p>Below is an example showing orphaned locks and using XACT_ABORT.</p>  <p>First, create a table and load some data:</p>  <blockquote>   <pre class="code"><span style="color: blue;">create table </span><span style="color: teal;">##test </span><span style="color: gray;">(</span><span style="color: teal;">id </span><span style="color: blue;">int</span><span style="color: gray;">)
</span><span style="color: blue;">go

insert into </span><span style="color: teal;">##test </span><span style="color: blue;">values </span><span style="color: gray;">(</span>1<span style="color: gray;">);
</span><span style="color: blue;">insert into </span><span style="color: teal;">##test </span><span style="color: blue;">values </span><span style="color: gray;">(</span>2<span style="color: gray;">);
</span><span style="color: blue;">insert into </span><span style="color: teal;">##test </span><span style="color: blue;">values </span><span style="color: gray;">(</span>3<span style="color: gray;">);
</span><span style="color: blue;">insert into </span><span style="color: teal;">##test </span><span style="color: blue;">values </span><span style="color: gray;">(</span>4<span style="color: gray;">);
</span><span style="color: blue;">insert into </span><span style="color: teal;">##test </span><span style="color: blue;">values </span><span style="color: gray;">(</span>5<span style="color: gray;">);
</span></pre>
</blockquote>



<p>Then create a stored procedure that will have enough of a delay to cause a Command Timeout in .NET:</p>

<blockquote>
  <pre class="code"><span style="color: blue;">create proc </span><span style="color: teal;">usp_AddNumber
</span><span style="color: gray;">(
    </span><span style="color: teal;">@id </span><span style="color: blue;">int</span><span style="color: gray;">,
    </span><span style="color: teal;">@newid </span><span style="color: blue;">int
</span><span style="color: gray;">)
</span><span style="color: blue;">as
begin tran
    </span><span style="color: magenta;">update </span><span style="color: teal;">##test </span><span style="color: blue;">set </span><span style="color: teal;">id </span><span style="color: gray;">= </span><span style="color: teal;">@newid </span><span style="color: blue;">where </span><span style="color: teal;">id </span><span style="color: gray;">= </span><span style="color: teal;">@id</span><span style="color: gray;">;
    </span><font style="background-color: rgb(255, 255, 0);"><span style="color: blue;">waitfor delay </span><span style="color: red;">'00:01:00.000'</span></font><span style="color: gray;"><font style="background-color: rgb(255, 255, 0);">;</font>
</span><span style="color: blue;">commit tran
go

</span></pre>
</blockquote>


<p>The following simple .NET code will call the stored procedure and fail due to a Command Timeout because of the WAITFOR exceeding the timeout allowed by the SqlCommand object (default is 30 seconds):</p>

<pre class="code"><span style="background: white; color: black;">        </span><span style="background: white; color: blue;">private void </span><span style="background: white; color: black;">btn_xact_btn_Click(</span><span style="background: white; color: blue;">object </span><span style="background: white; color: black;">sender, </span><span style="background: white; color: rgb(43, 145, 175);">EventArgs </span><span style="background: white; color: black;">e)
        {
            </span><span style="background: white; color: rgb(43, 145, 175);">SqlConnectionStringBuilder </span><span style="background: white; color: black;">cnString = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">SqlConnectionStringBuilder</span><span style="background: white; color: black;">();

            cnString.InitialCatalog = </span><span style="background: white; color: rgb(163, 21, 21);">&quot;tempdb&quot;</span><span style="background: white; color: black;">;
            cnString.IntegratedSecurity = </span><span style="background: white; color: blue;">true</span><span style="background: white; color: black;">;
            cnString.DataSource = </span><span style="background: white; color: rgb(163, 21, 21);">&quot;.&quot;</span><span style="background: white; color: black;">;

            </span><span style="background: white; color: blue;">using </span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(43, 145, 175);">SqlConnection </span><span style="background: white; color: black;">cn = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">SqlConnection</span><span style="background: white; color: black;">(cnString.ToString()))
            {
                cn.Open();
                </span><span style="background: white; color: rgb(43, 145, 175);">SqlCommand </span><span style="background: white; color: black;">cmd = </span><span style="background: white; color: blue;">new </span><span style="background: white; color: rgb(43, 145, 175);">SqlCommand</span><span style="background: white; color: black;">(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;usp_AddNumber&quot;</span><span style="background: white; color: black;">, cn);
                cmd.CommandType = </span><span style="background: white; color: rgb(43, 145, 175);">CommandType</span><span style="background: white; color: black;">.StoredProcedure;

                </span><span style="background: white; color: rgb(43, 145, 175);">SqlParameter </span><span style="background: white; color: black;">p1 = cmd.Parameters.Add(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;id&quot;</span><span style="background: white; color: black;">, </span><span style="background: white; color: rgb(43, 145, 175);">SqlDbType</span><span style="background: white; color: black;">.Int);
                p1.Value = 4;

                </span><span style="background: white; color: rgb(43, 145, 175);">SqlParameter </span><span style="background: white; color: black;">p2 = cmd.Parameters.Add(</span><span style="background: white; color: rgb(163, 21, 21);">&quot;newid&quot;</span><span style="background: white; color: black;">, </span><span style="background: white; color: rgb(43, 145, 175);">SqlDbType</span><span style="background: white; color: black;">.Int);
                p2.Value = 3;

                </span><span style="background: white; color: rgb(43, 145, 175);">Int32 </span><span style="background: white; color: black;">RowsAffected = cmd.ExecuteNonQuery();
            }
        }</span></pre>




<p><strong>BEFORE</strong> the timeout, we see the locks taken:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/1273.clip_image002_3E016110.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/1273.clip_5F00_image002_5F00_3E016110.jpg"><img title="clip_image002" style="display: inline; background-image: none;" border="0" alt="clip_image002" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/6545.clip_image002_thumb_00903AE2.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/6545.clip_5F00_image002_5F00_thumb_5F00_00903AE2.jpg" width="699" height="140" /></a></p>

<p><strong>AFTER</strong> the timeout hits, we see the _<i>same</i>_ locks still in place:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/3817.clip_image004_52268F67.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/3817.clip_5F00_image004_5F00_52268F67.jpg"><img title="clip_image004" style="display: inline; background-image: none;" border="0" alt="clip_image004" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/3817.clip_image004_thumb_3DC0C9DC.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/3817.clip_5F00_image004_5F00_thumb_5F00_3DC0C9DC.jpg" width="700" height="140" /></a></p>

<p>If we search for a request for SPID 55 – the session ID holding the locks, we see nothing:</p>

<blockquote>
  <pre class="code"><span style="color: blue;">select </span><span style="color: gray;">* </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_exec_requests </span><span style="color: blue;">where </span><span style="color: teal;">session_id </span><span style="color: gray;">= </span>55
  </pre>
</blockquote>


<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0160.clip_image006_20C77F3A.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0160.clip_5F00_image006_5F00_20C77F3A.jpg"><img title="clip_image006" style="display: inline; background-image: none;" border="0" alt="clip_image006" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/4035.clip_image006_thumb_708CBC51.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/4035.clip_5F00_image006_5F00_thumb_5F00_708CBC51.jpg" width="709" height="89" /></a></p>

<p>When the timeout hits and the client sends a cancel or disconnects, we see the Attention event in SQL Server:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/2388.clip_image008_2FD63616.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/2388.clip_5F00_image008_5F00_2FD63616.jpg"><img title="clip_image008" style="display: inline; background-image: none;" border="0" alt="clip_image008" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/4034.clip_image008_thumb_53328EE1.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/4034.clip_5F00_image008_5F00_thumb_5F00_53328EE1.jpg" width="791" height="60" /></a></p>

<p>For more information on an Attention event, refer to MSDN here:</p>

<blockquote>
  <p>Attention Event Class
    <br /><a title="https://msdn.microsoft.com/en-US/library/ms190979(v=sql.110).aspx" href="https://msdn.microsoft.com/en-US/library/ms190979(v=sql.110).aspx">https://msdn.microsoft.com/en-US/library/ms190979(v=sql.110).aspx</a></p>
</blockquote>

<p>One solution may be to terminate the process/application if that is feasible (but may not be if this is a middleware component or application server).&#160; If you see the session id but it has no active request, then killing the session (kill 55) can also release these locks.&#160; If I stop my .NET application – then my locks are gone.&#160; I can also kill the connection.&#160; However be aware that killing the connection (or hard terminating the application) may cause SQL Server to go into a lengthy rollback if the transaction has done a large amount of work.</p>

<p>If you want to know what application did this – which may or may not be useful based on the application architecture (if it is using middleware, etc..) - then we could:</p>

<pre class="code"><span style="color: blue;">select </span><span style="color: teal;">s</span><span style="color: gray;">.</span><span style="color: magenta;">host_name</span><span style="color: gray;">, </span><span style="color: teal;">c</span><span style="color: gray;">.</span><span style="color: teal;">client_net_address</span><span style="color: gray;">, </span><span style="color: teal;">s</span><span style="color: gray;">.</span><span style="color: teal;">host_process_id </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_exec_sessions </span><span style="color: teal;">s
    </span><span style="color: gray;">inner join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_exec_connections </span><span style="color: teal;">c
    </span><span style="color: blue;">on </span><span style="color: teal;">s</span><span style="color: gray;">.</span><span style="color: teal;">session_id </span><span style="color: gray;">= </span><span style="color: teal;">c</span><span style="color: gray;">.</span><span style="color: teal;">session_id
    </span><span style="color: blue;">where </span><span style="color: teal;">s</span><span style="color: gray;">.</span><span style="color: teal;">session_id </span><span style="color: gray;">= </span>55
</pre>




<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0207.clip_image010_0C29204A.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0207.clip_5F00_image010_5F00_0C29204A.jpg"><img title="clip_image010" style="display: inline; background-image: none;" border="0" alt="clip_image010" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/3835.clip_image010_thumb_6205842F.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/3835.clip_5F00_image010_5F00_thumb_5F00_6205842F.jpg" width="424" height="90" /></a></p>

<p>You could then go to system ASKJ-W520, find process id 5748 and see what it is doing or was doing (again it could be a mid-tier web or application server and may not be useful).</p>

<p>So, if we change the stored procedure to:</p>

<pre class="code"><span style="color: blue;">alter proc </span><span style="color: teal;">usp_AddNumber
</span><span style="color: gray;">(
    </span><span style="color: teal;">@id </span><span style="color: blue;">int</span><span style="color: gray;">,
    </span><span style="color: magenta;">newid </span><span style="color: blue;">int
</span><span style="color: gray;">)
</span><span style="color: blue;">as
    <font style="background-color: rgb(255, 255, 0);">set xact_abort on</font>
    begin tran
        </span><span style="color: magenta;">update </span><span style="color: teal;">##test </span><span style="color: blue;">set </span><span style="color: teal;">id </span><span style="color: gray;">= </span><span style="color: teal;">@newid </span><span style="color: blue;">where </span><span style="color: teal;">id </span><span style="color: gray;">= </span><span style="color: teal;">@id</span><span style="color: gray;">;
        </span><font style="background-color: rgb(255, 255, 0);"><span style="color: blue;">waitfor delay </span><span style="color: red;">'00:01:00.000'</span></font><span style="color: gray;"><font style="background-color: rgb(255, 255, 0);">;</font>
    </span><span style="color: blue;">commit tran
go

</span></pre>

<p>Then, when we hit the timeout, we have no leftover locks:</p>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/7142.clip_image012_3286EF96.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/7142.clip_5F00_image012_5F00_3286EF96.jpg"><img title="clip_image012" style="display: inline; background-image: none;" border="0" alt="clip_image012" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/8713.clip_image012_thumb_609079E9.jpg" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/8713.clip_5F00_image012_5F00_thumb_5F00_609079E9.jpg" width="703" height="100" /></a></p>

<p>So this may be as simple as killing the connection and identifying the application to see what was done (though in middleware this may not be very helpful).&#160; Again, remember – killing it may incur a lengthy rollback process.&#160; </p>

<p>If this specific issue is causing you problems, you should start by figuring out why the processing is taking so long to see if you can shorten it through tuning or breaking it into smaller transactions.&#160; Otherwise, you can consider increasing the timeout on the Command object.</p>

<p>- Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>Sequence Objects in SQL 2012 and SQL 2008</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/sequence-objects-in-sql-2012-and-sql-2008</link>
      <pubDate>Mon, 08 Oct 2012 07:42:00 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/10/08/sequence-objects-in-sql-2012-and-sql-2008/</guid>
      <description><![CDATA[&#160;  Sequence Objects are new starting in SQL Server 2012.&#160; They work similarly to an...]]></description>
      <content:encoded><![CDATA[<p>&#160;</p>  <p>Sequence Objects are new starting in SQL Server 2012.&#160; They work similarly to an IDENTITY value, but where the IDENTITY value is scoped to a specific column in a specific table, the Sequence Object is scoped to the entire database and controlled by application code.&#160; This can allow you to synchronize seed values across multiple tables that reference one another in a parent child relationship.&#160; Or, with a little bit of code you can also take control on whether or not the next value is used or saved for the next INSERT should the current transaction be rolled back (the IDENTITY value is lost and creates a gap when an INSERT is rolled back).&#160; For applications that require sequence numbering schemes without gaps, Sequence Objects do not solve that entirely.&#160; If a record is deleted or in concurrent inserts with multiple users where one transaction fails – gaps can still appear in your table as the sequence value is not re-used.&#160; To satisfy that requirement, you will still need to create a mechanism (commonly a table of values) yourself and manage them in a way where unused or deleted values are returned to the master table.&#160; However, Sequence Objects give us much greater flexibility in our design with auto-generated number sequences.&#160; To create a Sequence Object in SQL Server 2012, you can simply use the following:</p>  <p>&#160;</p>  <blockquote>   <pre class="csharpcode"><pre class="code"><span style="color: green;">-- Create a Sequence Object to start at 1 and increment by 1
</span><span style="color: blue;">CREATE </span><span style="color: teal;">SEQUENCE dbo</span><span style="color: gray;">.</span><span style="color: teal;">NextCustomerID
    </span><span style="color: blue;">as BIGINT
    </span><span style="color: teal;">START </span><span style="color: blue;">WITH </span>1
    <span style="color: teal;">INCREMENT </span><span style="color: blue;">BY </span>1<span style="color: gray;">;
</span><span style="color: blue;">GO

</span><span style="color: green;">-- Get the next available ID
</span><span style="color: blue;">DECLARE </span><span style="color: teal;">@CustID </span><span style="color: blue;">BIGINT</span><span style="color: gray;">;
</span><span style="color: blue;">SELECT </span><span style="color: teal;">@CustID </span><span style="color: gray;">= </span><span style="color: blue;">NEXT </span><span style="color: teal;">VALUE </span><span style="color: blue;">FOR </span><span style="color: teal;">dbo</span><span style="color: gray;">.</span><span style="color: teal;">NextCustomerID</span><span style="color: gray;">;
</span><span style="color: blue;">SELECT </span><span style="color: teal;">@CustID </span><span style="color: blue;">as </span><span style="color: red;">'Customer ID'</span><span style="color: gray;">;
</span></pre></pre>
</blockquote>

<p></p>

<p>You can get more information on Sequence Objects here:</p>

<p>Sequence Numbers
  <br /><a title="https://msdn.microsoft.com/en-us/library/ff878058.aspx" href="https://msdn.microsoft.com/en-us/library/ff878058.aspx">https://msdn.microsoft.com/en-us/library/ff878058.aspx</a></p>

<p>CREATE SEQUENCE (Transact-SQL)
  <br /><a title="https://msdn.microsoft.com/en-us/library/ff878091.aspx" href="https://msdn.microsoft.com/en-us/library/ff878091.aspx">https://msdn.microsoft.com/en-us/library/ff878091.aspx</a></p>

<p>&#160;</p>

<p>In SQL Server 2008 R2 and earlier, Sequence objects were not available.&#160; To provide this functionality, we have to build some constructs that allow us to mimic this behavior.</p>

<p>To satisfy the same the requirements as the Sequence Object, a common solution is to build dedicated table with an IDENTITY value where the last IDENTITY value can be returned from within a Stored Procedure or a Function:</p>

<blockquote>
  <pre class="code"><span style="color: blue;">CREATE TABLE </span><span style="color: teal;">dbo</span><span style="color: gray;">.</span><span style="color: teal;">GlobalSequence
</span><span style="color: gray;">(
       </span><span style="color: teal;">id </span><span style="color: blue;">INT IDENTITY</span><span style="color: gray;">(</span>1<span style="color: gray;">,</span>1<span style="color: gray;">)
)
</span><span style="color: blue;">go

BEGIN TRAN

INSERT INTO </span><span style="color: teal;">dbo</span><span style="color: gray;">.</span><span style="color: teal;">GlobalSequence 
       </span><span style="color: blue;">OUTPUT </span><span style="color: teal;">inserted</span><span style="color: gray;">.</span><span style="color: teal;">id
</span><span style="color: blue;">DEFAULT VALUES

ROLLBACK TRAN
</span></pre>

  <pre class="code"><span style="color: blue;"></span></pre>
  </blockquote>

<p>If you must not have gaps in your table in the event of a rolled back transaction or deleted record, you could remove the ROLLBACK TRAN operation (replacing it with a COMMIT) and either delete values once they are committed in your application or use a secondary BIT column to “tombstone” values once they are used.&#160; </p>

<p>Finally, in high throughput/high performance situations it is common to want to pre-allocate a block of numbers ahead of time.&#160; In SQL Server 2012 Sequence Objects, this is handled using the CACHE statement.&#160; For the SQL 2008 R2 and earlier solution above, you can do this in a couple of ways.&#160; One way would be to run a background task (a scheduled task in SQL Agent) that handles allocating a configurable block of IDENTITY values during an off-peak time.&#160; Another solution – or perhaps a backup solution – would be to check the amount of remaining values each time or every nth time a value is requested and allocate more one it reaches a low-water mark.&#160; With the latter approach, most requests will not incur any extra overhead besides the size check but occasionally a user will wait while the table is re-populated.&#160;&#160; If pre-allocating values and not deleting them once they are committed, you will likely want to schedule a background process to clean up the custom sequence value table when values are not longer needed.</p>

<p>- Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>If a worker thread doesn’t yield, is it guaranteed to run?</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/if-a-worker-thread-doesnt-yield-is-it-guaranteed-to-run</link>
      <pubDate>Sun, 29 Jul 2012 17:05:18 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/07/29/if-a-worker-thread-doesnt-yield-is-it-guaranteed-to-run/</guid>
      <description><![CDATA[&nbsp;Put another way, can Windows preempt our worker thread and perform a context switch even...]]></description>
      <content:encoded><![CDATA[<p>&nbsp;</p><p>Put another way, can Windows preempt our worker thread and perform a context switch even though it has been “scheduled” by the SQL OS (SOS) and SQL thinks it is running?&nbsp; Of course it can.&nbsp; </p><p>SQL Server implements a cooperative scheduling mechanism to make the most efficient use of the CPUs as it can.&nbsp; However, Windows ultimately schedules the thread and uses a general purpose pre-emptive scheduler and does not give special considerations to SQL Server when the dispatcher selects a thread – there all just threads to Windows (though they can have priority).&nbsp; So if a higher priority thread comes in from an interrupt or if we’ve exhausted our quantum at the OS level and another ready thread is waiting from another process to run it’s timeslice, then our worker thread will get preempted, regardless of what SQL wants.&nbsp; SQL controls this behavior to the best of it’s ability amongst it’s own worker threads by making sure no more threads are viable for scheduling (from within SQL) than the number of CPUs available to SQL Server.&nbsp; Also, SQL Server realizes there is no sense in scheduling a thread that is waiting on a database resource – like a transactional lock – something that Windows doesn’t understand.&nbsp; If a thread reaches its quantum at the OS and no other threads are viable to the Windows dispatcher, we can get another quantum and maximize SQL Server’s use of the CPU. In this way, we hope to reduce context switches – pure overhead from an execution standpoint.&nbsp; SQL controls the scheduling of it’s own worker threads by placing them into wait states with APIs like WaitForSingleObject.&nbsp; Then when a thread is ready to run because a lock has been freed, a timer has expired, or a task / request has come in from a user, SQL Server signals it to come out of the wait state and execute.&nbsp; Even as it sits in the RUNNABLE queue, it is actually in one of these wait APIs (though the SQL status will be RUNNABLE).&nbsp; As the “running” thread leaves, part of it’s “good-citizen” cooperative scheduling responsibilities is to “signal” the next worker thread in the RUNNABLE queue so that it can get it’s 15ms of fame.</p><p>This is a good reason to limit as much as possible what other software executes on your SQL Server.&nbsp; However, let’s see an example stack taken from my machine where just this scenario happened.</p><p>First, let’s look at a “normal” example:</p><blockquote><pre class="csharpcode">ntoskrnl.exe!<font style="background-color: rgb(255, 255, 0);">KiSwapContext+0x7a</font>
ntoskrnl.exe!KeSignalGateBoostPriority+0x1c0
ntdll.dll!<font style="background-color: rgb(255, 255, 0);">ZwWaitForSingleObject+0xa</font>
KERNELBASE.dll!WaitForSingleObjectEx+0x79
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">SOS_Scheduler::SwitchContext+0x26d</font>
sqlservr.exe!SOS_Scheduler::SuspendNonPreemptive+0xca
sqlservr.exe!SOS_Scheduler::Suspend+0x2d
sqlservr.exe!EventInternal&lt;Spinlock&lt;153,1,0&gt; &gt;::Wait+0x1a8
sqlservr.exe!EventInternal&lt;Spinlock&lt;153,1,0&gt; &gt;::WaitAllowPrematureWakeup+0x59
sqlservr.exe!CXPacketList::RemoveHead+0xf0
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">CXPipe::Pull+0x8b</font>
sqlservr.exe!CXTransLocal::AllocateBuffers+0x5b
sqlservr.exe!CQScanXProducerNew::AllocateBuffers+0x31
sqlservr.exe!CQScanXProducerNew::GetRowHelper+0x1c2
sqlservr.exe!FnProducerOpen+0x58
sqlservr.exe!FnProducerThread+0x4df
sqlservr.exe!SubprocEntrypoint+0x794
sqlservr.exe!SOS_Task::Param::Execute+0x12a
sqlservr.exe!SOS_Scheduler::RunTask+0x96
sqlservr.exe!SOS_Scheduler::ProcessTasks+0x128
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">SchedulerManager::WorkerEntryPoint+0x2d2</font>
sqlservr.exe!SystemThread::RunWorker+0xcc
sqlservr.exe!SystemThreadDispatcher::ProcessWorker+0x2db
sqlservr.exe!SchedulerManager::ThreadEntryPoint+0x173
MSVCR80.dll!_callthreadstartex+0x17
MSVCR80.dll!_threadstartex+0x84
kernel32.dll!BaseThreadInitThunk+0xd
ntdll.dll!RtlUserThreadStart+0x1d
</pre></blockquote><p><br>So here we have a thread that is part of a parallel query that goes into a wait.&nbsp; Ever see those CXPACKET waits?&nbsp; Well, you’re looking at one now.&nbsp; So whlie we wait on CXPACKET or any other wait type – we can’t do anything.&nbsp; Let’s “switch context” and have the SQL OS (SOS) take us off the scheduler – let someone else have their time – and we can be signaled when it’s time to go again.&nbsp; As we “switch”, the SOS scheduler puts us in a wait state (waiting on an event) with WaitForSingleObject.&nbsp; At the frame that reads ZwWaitForSingleObject, you are seeing the transition from user mode into kernel mode as Windows takes over.&nbsp; Then at the top of the stack, the Windows dispatcher records our context record and switches us off the CPU and finds which thread is ready to run – which is very likely NOT another SQL Server thread in *this case* – but on a dedicated SQL Server we’d like it to be – and most of the time it should be.</p><p>Now, let’s see if SQL can have the rug pulled out from under it… Here’s one:</p><blockquote><pre class="csharpcode">ntoskrnl.exe!<font style="background-color: rgb(255, 255, 0);">KiSwapContext+0x7a</font>
ntoskrnl.exe!KiCommitThreadWait+0x1d2
ntoskrnl.exe!KeWaitForSingleObject+0x19f
ntoskrnl.exe!KiSuspendThread+0x54
ntoskrnl.exe!KiDeliverApc+0x201
ntoskrnl.exe!KiApcInterrupt+0xd7
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">CQScanXProducerNew::GetRowHelper+0x289</font>
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">FnProducerOpen+0x58</font>
sqlservr.exe!FnProducerThread+0x4df
sqlservr.exe!SubprocEntrypoint+0x794
sqlservr.exe!SOS_Task::Param::Execute+0x12a
sqlservr.exe!SOS_Scheduler::RunTask+0x96
sqlservr.exe!SOS_Scheduler::ProcessTasks+0x128
sqlservr.exe!SchedulerManager::WorkerEntryPoint+0x2d2
sqlservr.exe!SystemThread::RunWorker+0xcc
sqlservr.exe!SystemThreadDispatcher::ProcessWorker+0x2db
sqlservr.exe!SchedulerManager::ThreadEntryPoint+0x173
MSVCR80.dll!_callthreadstartex+0x17
MSVCR80.dll!_threadstartex+0x84
kernel32.dll!BaseThreadInitThunk+0xd
ntdll.dll!RtlUserThreadStart+0x1d
</pre></blockquote><p>Notice at the top – Windows has performed the context switch and let someone else run.&nbsp; Once again, Windows will save our execution context in something known as a context record (so it knows where it was and what we were doing when we finally do get back on the CPU) and let another thread execute – very likely a thread from a different process.&nbsp; Also, notice that the last frame from SQL Server (sqlservr!*) is more parallelism code.&nbsp; There is no call to sleep, no call to SwitchContext, nothing from the SQL OS at all.&nbsp; We are just rudely interrupted by the kernel (ntoskrnl.exe) and told –&nbsp; you’re done.&nbsp; Actually, at this point it was processing the APC queue (part of the kernel) and went into it’s own WaitForSingleObject call as a part of the context switch – but not one invoked by SQL Server.&nbsp; Also, kernel stacks work the same as user mode stacks – so other kernel code could have already run and been “popped” off the stack at this point.&nbsp; We’ll get more time in a matter of milliseconds, but the more this happens, the more your SQL code waits, the more the duration goes up – and yet no progress is made.</p><p>So you really want to limit how much non-SQL server software you execute on your server, SQL Server can’t control other processes or Window’s scheduling of those processes.</p><p>Finally, how did I get this?&nbsp; First, I used Mark Russinovich’s excellent Process Explorer utility to capture both the user and kernel mode stacks in one nice combined stack trace.&nbsp; To easily “create” this mess and find an offending thread, I ran a very busy query (a cross join) and also ran an external utility I wrote that does nothing but burn cpu, it’s literally called “EatCPU”.</p><p>- Jay</p><pre class="csharpcode">&nbsp;</pre>]]></content:encoded>
    </item>
    <item>
      <title>Do waiting or suspended tasks tie up a worker thread?</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/do-waiting-or-suspended-tasks-tie-up-a-worker-thread</link>
      <pubDate>Sun, 29 Jul 2012 14:32:44 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/07/29/do-waiting-or-suspended-tasks-tie-up-a-worker-thread/</guid>
      <description><![CDATA[&nbsp;I had a discussion the other day with someone about worker threads and their relation to...]]></description>
      <content:encoded><![CDATA[<p>&nbsp;</p><p>I had a discussion the other day with someone about worker threads and their relation to tasks.&nbsp; I thought a quick demo might be worthwhile.&nbsp; When we have tasks that are waiting on a resource (whether it be a timer or a resource like a lock) we are tying up a worker thread.&nbsp; A worker thread is assigned to a task for the duration of that task.&nbsp; For most queries, this means for the duration of the user’s request or query.&nbsp; Let’s look at two examples below.</p><p>We could verify that the worker thread is tied up by verifying the state the worker thread is in and that it is assigned to our tasks through the following two DMVs:</p><blockquote><pre class="code"><span style="color: blue;">select </span><span style="color: gray;">* </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_workers
</span><span style="color: blue;">select </span><span style="color: gray;">* </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_tasks
</span></pre></blockquote><p>If we start a 5 minute delay to tie up a worker thread using session 55 as follows:</p><blockquote style="margin-right: 0px;" dir="ltr"><pre class="code"><span style="color: blue;">waitfor delay </span><span style="color: red;">'00:05:00'
</span></pre></blockquote><p>Then we can use the following to verify our worker thread is assigned to our task and suspended while it waits on the timer:</p><blockquote><pre class="code"><span style="color: blue;">select 
    </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">worker_address</span><span style="color: gray;">,
    </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: blue;">state</span><span style="color: gray;">,
    </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">task_address</span><span style="color: gray;">,
    </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">session_id
</span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_tasks </span><span style="color: teal;">t
    </span><span style="color: gray;">inner join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_workers </span><span style="color: teal;">w
    </span><span style="color: blue;">on </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">worker_address </span><span style="color: gray;">= </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">worker_address
    </span><span style="color: blue;">where </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">session_id </span><span style="color: gray;">= </span>55
</pre></blockquote><p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/2045.image_2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/2045.image_5F00_2.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0804.image_thumb.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0804.image_5F00_thumb.png" width="562" height="95"></a></p><p>&nbsp;</p><p>However, we can also get the worker’s OS thread ID and view the call stack to see that it is not merely waiting for work to do – but is tied up waiting to complete.&nbsp; For the above worker thread running on SPID 55, we can run the following to get the os thread id:<br></p><blockquote><pre class="code"><span style="color: blue;">select </span><span style="color: teal;">os_thread_id </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_tasks </span><span style="color: teal;">t
    </span><span style="color: gray;">inner join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_workers </span><span style="color: teal;">w
    </span><span style="color: blue;">on </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">worker_address </span><span style="color: gray;">= </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">worker_address
    </span><span style="color: gray;">inner join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_threads </span><span style="color: teal;">o
    </span><span style="color: blue;">on </span><span style="color: teal;">o</span><span style="color: gray;">.</span><span style="color: teal;">worker_address </span><span style="color: gray;">= </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">worker_address
 </span><span style="color: blue;">where </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">session_id </span><span style="color: gray;">= </span>55
</pre></blockquote><p>this gives us:</p><p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/4617.image_4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/4617.image_5F00_4.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/5277.image_thumb_1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/5277.image_5F00_thumb_5F00_1.png" width="240" height="85"></a></p><p>Now we can get the stack trace of os thread 8376.&nbsp; And it is:</p><blockquote><pre class="csharpcode">kernel32.dll!SignalObjectAndWait+0x110
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">SOS_Scheduler::Switch+0x181</font>
sqlservr.exe!SOS_Scheduler::SuspendNonPreemptive+0xca
sqlservr.exe!SOS_Scheduler::Suspend+0x2d
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">SOS_Task::Sleep+0xec</font>
sqlservr.exe!CStmtWait::XretExecute+0x38b
sqlservr.exe!CMsqlExecContext::ExecuteStmts&lt;1,1&gt;+0x375
sqlservr.exe!CMsqlExecContext::FExecute+0x97e
sqlservr.exe!CSQLSource::Execute+0x7b5
sqlservr.exe!process_request+0x64b
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">process_commands+0x4e5</font>
sqlservr.exe!SOS_Task::Param::Execute+0x12a
sqlservr.exe!SOS_Scheduler::RunTask+0x96
sqlservr.exe!SOS_Scheduler::ProcessTasks+0x128
sqlservr.exe!SchedulerManager::WorkerEntryPoint+0x2d2
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">SystemThread::RunWorker+0xcc</font>
sqlservr.exe!SystemThreadDispatcher::ProcessWorker+0x2db
sqlservr.exe!SchedulerManager::ThreadEntryPoint+0x173
MSVCR80.dll!_callthreadstartex+0x17
MSVCR80.dll!_threadstartex+0x84
kernel32.dll!BaseThreadInitThunk+0xd
ntdll.dll!RtlUserThreadStart+0x1d
</pre><pre class="csharpcode">&nbsp;</pre></blockquote><p>From the highlighted sections in the stack trace above, we can see this is a worker thread that is processing commands (our WAITFOR DELAY statement).&nbsp; It has entered a sleep as a result of our WAITFOR DELAY call and SQL Server OS has switched it off the scheduler since there isn’t anything it can do for 5 minutes.&nbsp; Once the timer expires, the thread will be signaled and can be placed back into the RUNNABLE queue in case there is any more work for it to do.</p><p>So our thread is in effect tied up and can’t do any work for 5 minutes.&nbsp; Extensive use of WAITFOR could be a good way to choke the system.&nbsp; What about normal resources?&nbsp; What if we are waiting to obtain a shared lock (LCK_M_S)?&nbsp; Same story… Let’s look…</p><p>We can create a simple table and do an insert without closing the transaction to hold the locks…</p><blockquote><pre class="code"><span style="color: blue;">create table </span><span style="color: teal;">Customers
</span><span style="color: gray;">(
    </span><span style="color: teal;">ID </span><span style="color: blue;">INT IDENTITY</span><span style="color: gray;">(</span>1<span style="color: gray;">,</span>1<span style="color: gray;">) </span><span style="color: blue;">PRIMARY KEY CLUSTERED</span><span style="color: gray;">,
    </span><span style="color: teal;">FIRSTNAME </span><span style="color: blue;">NVARCHAR</span><span style="color: gray;">(</span>30<span style="color: gray;">),
    </span><span style="color: teal;">LASTNAME </span><span style="color: blue;">NVARCHAR</span><span style="color: gray;">(</span>30<span style="color: gray;">)
)
</span><span style="color: blue;">ON </span><span style="color: teal;">[PRIMARY]
</span><span style="color: blue;">GO

BEGIN TRAN
    INSERT INTO </span><span style="color: teal;">CUSTOMERS </span><span style="color: gray;">(</span><span style="color: teal;">FIRSTNAME</span><span style="color: gray;">, </span><span style="color: teal;">LASTNAME</span><span style="color: gray;">) </span><span style="color: blue;">VALUES </span><span style="color: gray;">(</span><span style="color: red;">'John'</span><span style="color: gray;">, </span><span style="color: red;">'Doe'</span><span style="color: gray;">)
    </span><span style="color: blue;">INSERT INTO </span><span style="color: teal;">CUSTOMERS </span><span style="color: gray;">(</span><span style="color: teal;">FIRSTNAME</span><span style="color: gray;">, </span><span style="color: teal;">LASTNAME</span><span style="color: gray;">) </span><span style="color: blue;">VALUES </span><span style="color: gray;">(</span><span style="color: red;">'Jane'</span><span style="color: gray;">, </span><span style="color: red;">'Doe'</span><span style="color: gray;">)
    </span><span style="color: blue;">INSERT INTO </span><span style="color: teal;">CUSTOMERS </span><span style="color: gray;">(</span><span style="color: teal;">FIRSTNAME</span><span style="color: gray;">, </span><span style="color: teal;">LASTNAME</span><span style="color: gray;">) </span><span style="color: blue;">VALUES </span><span style="color: gray;">(</span><span style="color: red;">'George'</span><span style="color: gray;">, </span><span style="color: red;">'Doe'</span><span style="color: gray;">)
</span></pre></blockquote><p><br>Now from another session (session 56), we can try to read that table – which will block hopelessly…</p><blockquote><pre class="code"><span style="color: blue;">select </span><span style="color: gray;">* </span><span style="color: blue;">from </span><span style="color: teal;">Customers</span></pre></blockquote><p><span style="color: teal;"><font color="#000000">Once again, we use the query from above to get our OS Thread ID:<br></font></span></p><blockquote><pre class="code"><span style="color: blue;">select </span><span style="color: teal;">os_thread_id </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_tasks </span><span style="color: teal;">t
    </span><span style="color: gray;">inner join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_workers </span><span style="color: teal;">w
    </span><span style="color: blue;">on </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">worker_address </span><span style="color: gray;">= </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">worker_address
    </span><span style="color: gray;">inner join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">dm_os_threads </span><span style="color: teal;">o
    </span><span style="color: blue;">on </span><span style="color: teal;">o</span><span style="color: gray;">.</span><span style="color: teal;">worker_address </span><span style="color: gray;">= </span><span style="color: teal;">w</span><span style="color: gray;">.</span><span style="color: teal;">worker_address
 </span><span style="color: blue;">where </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">session_id </span><span style="color: gray;">= </span>56
</pre><pre class="code">&nbsp;</pre></blockquote><p><a href="https://11011.net/software/vspaste"><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/7824.image_6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/7824.image_5F00_6.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/8322.image_thumb_2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/8322.image_5F00_thumb_5F00_2.png" width="281" height="107"></a></a></p><span style="color: teal;"><font color="#000000"><p><br>And now we are ready to get the stack for this thread:</p><blockquote><pre class="csharpcode">kernel32.dll!SignalObjectAndWait+0x110
sqlservr.exe!SOS_Scheduler::Switch+0x181
sqlservr.exe!SOS_Scheduler::SuspendNonPreemptive+0xca
sqlservr.exe!SOS_Scheduler::Suspend+0x2d
sqlservr.exe!EventInternal&lt;Spinlock&lt;153,1,0&gt; &gt;::Wait+0x1a8
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">LockOwner::Sleep+0x1f7</font>
sqlservr.exe!lck_lockInternal+0xd7a
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">GetLock+0x1eb</font>
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">BTreeRow::AcquireLock+0x1f9</font>
sqlservr.exe!IndexRowScanner::AcquireNextRowLock+0x1e1
sqlservr.exe!IndexDataSetSession::GetNextRowValuesInternal+0x1397
sqlservr.exe!RowsetNewSS::FetchNextRow+0x159
sqlservr.exe!CQScanRowsetNew::GetRowWithPrefetch+0x47
sqlservr.exe!CQScanTableScanNew::GetRowDirectSelect+0x29
sqlservr.exe!CQScanTableScanNew::GetRow+0x71
sqlservr.exe!CQueryScan::GetRow+0x69
sqlservr.exe!CXStmtQuery::ErsqExecuteQuery+0x602
sqlservr.exe!CXStmtSelect::XretExecute+0x2dd
sqlservr.exe!CMsqlExecContext::ExecuteStmts&lt;1,1&gt;+0x375
sqlservr.exe!CMsqlExecContext::FExecute+0x97e
sqlservr.exe!CSQLSource::Execute+0x7b5
sqlservr.exe!process_request+0x64b
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">process_commands+0x4e5</font>
sqlservr.exe!SOS_Task::Param::Execute+0x12a
sqlservr.exe!SOS_Scheduler::RunTask+0x96
sqlservr.exe!SOS_Scheduler::ProcessTasks+0x128
sqlservr.exe!SchedulerManager::WorkerEntryPoint+0x2d2
sqlservr.exe!<font style="background-color: rgb(255, 255, 0);">SystemThread::RunWorker+0xcc</font>
sqlservr.exe!SystemThreadDispatcher::ProcessWorker+0x2db
sqlservr.exe!SchedulerManager::ThreadEntryPoint+0x173
MSVCR80.dll!_callthreadstartex+0x17
MSVCR80.dll!_threadstartex+0x84
kernel32.dll!BaseThreadInitThunk+0xd
ntdll.dll!RtlUserThreadStart+0x1d
</pre></blockquote></font></span><p>Again, our worker thread processes our command (the SELECT query) and goes into a sleep.&nbsp; Notice this is just the name of the method from the “LockOwner” class – not the same sleep as above that is bound to a timer.&nbsp; The SOS scheduler switches us off and we wait to be signaled that our lock is available.&nbsp; This thread is “tied up” – waiting to continue.<br><br>These are the reasons that massive blocking cases can eventually lead to worker thread depletion – and waits on THREADPOOL.</p><p>-Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>Finding Missing Dependencies</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/finding-missing-dependencies</link>
      <pubDate>Sun, 22 Jul 2012 15:15:00 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/07/22/finding-missing-dependencies/</guid>
      <description><![CDATA[&#160;  While working with a customer on a SQL port, I came across a system view that was new with...]]></description>
      <content:encoded><![CDATA[<p>&#160;</p>  <p>While working with a customer on a SQL port, I came across a system view that was new with SQL Server 2008.&#160; Have you ever needed to check your database code (stored procedures) to see if it references any missing objects?&#160; As of SQL Server 2008 this is easy thanks to:</p>  <blockquote>   <pre class="code"><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">sql_expression_dependencies
</span></pre>
</blockquote>

<p><span style="color: green;"><font color="#000000">More can be found here:</font></span></p>

<p><strong>sys.sql_expression_dependencies (Transact-SQL)
    <br /></strong><a title="https://msdn.microsoft.com/en-us/library/bb677315" href="https://msdn.microsoft.com/en-us/library/bb677315"><font style="font-weight: normal;">https://msdn.microsoft.com/en-us/library/bb677315</font></a></p>

<p>As with my customer’s case, issues like this can creep into code because of SQL Server’s Deferred Name Resolution Feature.&#160; This simply means SQL Server will let you compile a stored procedure that refers to an object that doesn’t yet exist.&#160; You can read more about this here:</p>

<p><a href="https://msdn.microsoft.com/en-us/library/ms190686(v=sql.105).aspx"><a title="https://msdn.microsoft.com/en-us/library/ms190686(v=sql.105).aspx" href="https://msdn.microsoft.com/en-us/library/ms190686(v=sql.105).aspx"><font style="font-weight: normal;">https://msdn.microsoft.com/en-us/library/ms190686(v=sql.105).aspx</font></a></a></p>

<p>In this situation, missing objects – and errors – may not be found until runtime.&#160; Using this system view, we can get an idea of what our exposure is to 208 errors = “Invalid Object Name”.</p>

<p>This example is a simple illustration for a table reference, but you can expand this to other object types as well.&#160; First, we create a stored procedure that references a table that doesn’t exist:</p>

<blockquote>
  <pre class="code"><span style="color: blue;">create procedure </span><span style="color: teal;">DNRproc
</span><span style="color: blue;">as
    </span><span style="color: green;">-- select from a non-existent table
    </span><span style="color: blue;">select </span><span style="color: gray;">* </span><span style="color: blue;">from </span><span style="color: teal;">dbo</span><span style="color: gray;">.</span><span style="color: blue;">Address
go
</span></pre>
</blockquote>


<p>Then, we execute:
  <br /></p>

<blockquote>
  <pre class="code"><span style="color: blue;">exec </span><span style="color: teal;">DNRproc
</span></pre>
</blockquote>

<p>and get:</p>

<blockquote>
  <pre class="code"><font color="#ff0000">Msg 208, Level 16, State 1, Procedure DNRproc, Line 4
Invalid object name 'dbo.Address'.
</font></pre>
</blockquote>


<p><font color="#000000">To find this missing object reference, we can use:</font></p>

<blockquote>
  <pre class="code"><span style="color: blue;">select
    </span><span style="color: magenta;">object_name</span><span style="color: gray;">(</span><span style="color: teal;">referencing_id</span><span style="color: gray;">) </span><span style="color: blue;">as </span><span style="color: red;">'object making reference'</span><span style="color: gray;">,
    </span><span style="color: teal;">referenced_class_desc</span><span style="color: gray;">,
    </span><span style="color: teal;">referenced_schema_name</span><span style="color: gray;">,
    </span><span style="color: teal;">referenced_entity_name </span><span style="color: blue;">as </span><span style="color: red;">'object name referenced'</span><span style="color: gray;">,
    (</span><span style="color: blue;">select </span><span style="color: magenta;">object_id </span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">objects </span><span style="color: blue;">where </span><span style="color: teal;">name </span><span style="color: gray;">= </span><span style="color: teal;">[referenced_entity_name]</span><span style="color: gray;">) </span><span style="color: blue;">as </span><span style="color: red;">'Object Found?'
</span><span style="color: blue;">from </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">sql_expression_dependencies </span><span style="color: teal;">e
    </span><span style="color: gray;">left join </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">tables </span><span style="color: teal;">t
    </span><span style="color: blue;">on </span><span style="color: teal;">e</span><span style="color: gray;">.</span><span style="color: teal;">referenced_entity_name </span><span style="color: gray;">= </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: teal;">name
</span></pre>

  <pre class="code"><span style="color: teal;"></span></pre>
</blockquote>

<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/3175.image_2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/3175.image_5F00_2.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/1513.image_thumb.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/1513.image_5F00_thumb.png" width="737" height="138" /></a></p>

<p>&#160;</p>

<p>A “NULL” value in the “Object Found?” column indicates the object was not found in sys.objects.&#160; Therefore, we can easily see that dbo.Address which was referenced by DNRproc was not found.&#160; </p>

<p>This doesn’t replace good coding and migration practices, but can be a helpful tool – and can be expanded upon to check for more objects than just missing tables.</p>

<p>-Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>Loading data with foreign keys</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/loading-data-with-foreign-keys</link>
      <pubDate>Sun, 15 Jul 2012 14:34:00 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/07/15/loading-data-with-foreign-keys/</guid>
      <description><![CDATA[&#160;  Working on a customer project the other day, I needed to load some data into a database that...]]></description>
      <content:encoded><![CDATA[<p>&#160;</p>  <p>Working on a customer project the other day, I needed to load some data into a database that had been scripted and re-created.&#160; The newly created database already had foreign keys in place which means for loading data (this was from SSIS), we had 2 options:</p>  <p>1) drop the foreign key constraints, load the data, re-apply the constraints   <br />2) load the data in the correct order so that parent tables are loaded first, followed by children, followed by grandchildren, etc…</p>  <p>I decided to give option 2 a try.&#160; In our work we were dynamically generating an SSIS package in C# – so we had some flexibility in deciding how to load the data.&#160; So what I needed was a way to identify the correct order described in option #2.&#160; </p>  <p>The idea is fairly straightforward.&#160; We needed to find the parent tables that have references to them but don’t reference anything themselves.&#160; Then find all the objects that reference those tables, and so on…&#160; The system view sys.foreign_keys is our primary tool for this.&#160; We need to track changes at each level because a “child” table could reference tables at difference levels.&#160; In this case, we’re mostly interested in the lowest level reference to be sure all of it’s parent tables are loaded first.&#160; Finally, I found that with this method, self-referencing tables are problematic.&#160; In this version, I simply exclude those.&#160; If the data is loaded into that table in order, everything should be fine. </p>  <p>Here is the script I wrote for this – hope it helps:</p>  <p>&#160;</p>  <blockquote>   <pre class="code"><span style="color: blue;">DECLARE </span><span style="color: teal;">@FK_TABLE_ORDER </span><span style="color: blue;">TABLE
</span><span style="color: gray;">(
    </span><span style="color: teal;">FKLEVEL </span><span style="color: blue;">INT</span><span style="color: gray;">,
    </span><span style="color: teal;">OBJECTID </span><span style="color: blue;">INT
</span><span style="color: gray;">)

</span><span style="color: blue;">DECLARE </span><span style="color: teal;">@CHILDCOUNT </span><span style="color: blue;">INT</span><span style="color: gray;">, </span><span style="color: teal;">@CURRLEVEL </span><span style="color: blue;">INT
SELECT </span><span style="color: teal;">@CHILDCOUNT </span><span style="color: gray;">= </span>1<span style="color: gray;">, </span><span style="color: teal;">@CURRLEVEL </span><span style="color: gray;">= </span>0<span style="color: gray;">;

</span><span style="color: blue;">WITH </span><span style="color: teal;">Top_Level_Tables
</span><span style="color: blue;">AS
</span><span style="color: gray;">(
    </span><span style="color: blue;">SELECT
        </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: magenta;">object_id</span><span style="color: gray;">,
        </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: magenta;">schema_id</span><span style="color: gray;">,
        </span><span style="color: teal;">f</span><span style="color: gray;">.</span><span style="color: teal;">parent_object_id
    </span><span style="color: blue;">FROM </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">tables </span><span style="color: teal;">t
    </span><span style="color: gray;">INNER JOIN </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">foreign_keys </span><span style="color: teal;">f
    </span><span style="color: blue;">ON </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: magenta;">object_id </span><span style="color: gray;">= </span><span style="color: teal;">f</span><span style="color: gray;">.</span><span style="color: teal;">referenced_object_id
</span><span style="color: gray;">)
</span><span style="color: blue;">INSERT INTO </span><span style="color: teal;">@FK_TABLE_ORDER
</span><span style="color: blue;">SELECT DISTINCT </span>0<span style="color: gray;">, </span><span style="color: magenta;">object_id </span><span style="color: blue;">from </span><span style="color: teal;">Top_Level_Tables
    </span><span style="color: blue;">WHERE </span><span style="color: magenta;">object_id </span><span style="color: gray;">NOT IN (</span><span style="color: blue;">SELECT </span><span style="color: teal;">parent_object_id </span><span style="color: blue;">FROM </span><span style="color: teal;">Top_Level_Tables</span><span style="color: gray;">)

</span><span style="color: blue;">SELECT </span><span style="color: teal;">@CHILDCOUNT </span><span style="color: gray;">= ( </span><span style="color: blue;">SELECT </span><span style="color: magenta;">COUNT</span><span style="color: gray;">(*) </span><span style="color: blue;">FROM </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">foreign_keys 
                        </span><span style="color: blue;">WHERE </span><span style="color: teal;">referenced_object_id </span><span style="color: gray;">IN 
                        (</span><span style="color: blue;">SELECT </span><span style="color: teal;">OBJECTID </span><span style="color: blue;">FROM </span><span style="color: teal;">@FK_TABLE_ORDER </span><span style="color: blue;">WHERE </span><span style="color: teal;">FKLEVEL </span><span style="color: gray;">= </span><span style="color: teal;">@CURRLEVEL</span><span style="color: gray;">)
                     )

</span><span style="color: blue;">WHILE </span><span style="color: gray;">(</span><span style="color: teal;">@CHILDCOUNT </span><span style="color: gray;">&gt; </span>0<span style="color: gray;">)
 </span><span style="color: blue;">BEGIN
    
    SELECT </span><span style="color: teal;">@CURRLEVEL </span><span style="color: gray;">= </span><span style="color: teal;">@CURRLEVEL </span><span style="color: gray;">+ </span>1<span style="color: gray;">;

    </span><span style="color: blue;">INSERT INTO </span><span style="color: teal;">@FK_TABLE_ORDER
    </span><span style="color: blue;">SELECT DISTINCT
        </span><span style="color: teal;">@CURRLEVEL</span><span style="color: gray;">,
        </span><span style="color: teal;">parent_object_id
    </span><span style="color: blue;">FROM </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">foreign_keys 
    </span><span style="color: blue;">WHERE </span><span style="color: teal;">referenced_object_id </span><span style="color: gray;">IN 
        (</span><span style="color: blue;">SELECT </span><span style="color: teal;">OBJECTID </span><span style="color: blue;">FROM </span><span style="color: teal;">@FK_TABLE_ORDER
            </span><span style="color: blue;">WHERE </span><span style="color: teal;">FKLEVEL </span><span style="color: gray;">= (</span><span style="color: teal;">@CURRLEVEL </span><span style="color: gray;">- </span>1<span style="color: gray;">)
        ) AND
        </span><span style="color: teal;">referenced_object_id </span><span style="color: gray;">IS NOT NULL AND
        </span><span style="color: teal;">referenced_object_id </span><span style="color: gray;">!= </span><span style="color: teal;">parent_object_id

    </span><span style="color: blue;">SELECT </span><span style="color: teal;">@CHILDCOUNT </span><span style="color: gray;">= ( </span><span style="color: blue;">SELECT </span><span style="color: magenta;">COUNT</span><span style="color: gray;">(*) </span><span style="color: blue;">FROM </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">foreign_keys    
                            </span><span style="color: blue;">WHERE </span><span style="color: teal;">referenced_object_id </span><span style="color: gray;">IN 
                            (</span><span style="color: blue;">SELECT </span><span style="color: teal;">OBJECTID </span><span style="color: blue;">FROM </span><span style="color: teal;">@FK_TABLE_ORDER </span><span style="color: blue;">WHERE </span><span style="color: teal;">FKLEVEL </span><span style="color: gray;">= </span><span style="color: teal;">@CURRLEVEL</span><span style="color: gray;">)
                         )

    
 </span><span style="color: blue;">END

 INSERT INTO </span><span style="color: teal;">@FK_TABLE_ORDER
 </span><span style="color: blue;">SELECT </span>0<span style="color: gray;">, </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: magenta;">object_id </span><span style="color: blue;">FROM </span><span style="color: green;">sys</span><span style="color: gray;">.</span><span style="color: green;">tables </span><span style="color: teal;">t
 </span><span style="color: blue;">WHERE </span><span style="color: teal;">t</span><span style="color: gray;">.</span><span style="color: magenta;">object_id </span><span style="color: gray;">NOT IN (</span><span style="color: blue;">SELECT </span><span style="color: teal;">OBJECTID </span><span style="color: blue;">FROM </span><span style="color: teal;">@FK_TABLE_ORDER</span><span style="color: gray;">)

 </span><span style="color: blue;">SELECT </span><span style="color: magenta;">OBJECT_NAME</span><span style="color: gray;">(</span><span style="color: teal;">OBJECTID</span><span style="color: gray;">) </span><span style="color: blue;">as </span><span style="color: red;">'Table Name'</span><span style="color: gray;">, </span><span style="color: magenta;">MAX</span><span style="color: gray;">(</span><span style="color: teal;">FKLEVEL</span><span style="color: gray;">) </span><span style="color: blue;">as </span><span style="color: red;">'Load Order'
     </span><span style="color: blue;">FROM </span><span style="color: teal;">@FK_TABLE_ORDER </span><span style="color: blue;">GROUP BY </span><span style="color: teal;">OBJECTID 
     </span><span style="color: blue;">ORDER BY </span><span style="color: teal;">[Load Order] </span><span style="color: blue;">ASC
</span></pre>
</blockquote>

<p>-Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>Need to find the Database Version? Last Log Backup? Last DBCC execution? Ummm….</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/need-to-find-the-database-version-last-log-backup-last-dbcc-execution-ummm</link>
      <pubDate>Sun, 08 Jul 2012 15:45:00 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/07/08/need-to-find-the-database-version-last-log-backup-last-dbcc-execution-ummm/</guid>
      <description><![CDATA[Backup software and Maintenance plans usually take care of tracking backup schedules and...]]></description>
      <content:encoded><![CDATA[<p>   <br />Backup software and Maintenance plans usually take care of tracking backup schedules and maintenance schedules for us… but how else do we find this information inside SQL Server?&#160; The following query will get the last backup date and time from MSDB:</p>  <blockquote>   <pre class="code"><span style="color: blue;">select </span><span style="color: teal;">database_name</span><span style="color: gray;">, </span><span style="color: magenta;">max</span><span style="color: gray;">(</span><span style="color: teal;">backup_finish_date</span><span style="color: gray;">) </span><span style="color: blue;">as </span><span style="color: red;">'last backup' </span><span style="color: blue;">from </span><span style="color: teal;">dbo</span><span style="color: gray;">.</span><span style="color: teal;">backupset
    </span><span style="color: blue;">group by </span><span style="color: teal;">database_name
</span></pre>
  </blockquote>

<p><span style="color: teal;"><font color="#000000">And the error log records the last DBCC.&#160; </font></span></p>

<p><span style="color: teal;"><font color="#000000">Also, if you have access to the backup file, you can get the last backup timestamp and database version (in the backup file) using the RESTORE HEADERONLY command.</font></span></p>

<p>Though most of this is maintained and available in MSDB and other system base tables (database create date), I wanted to introduce you to the database boot page.&#160; This information (and other information) is also stored in each database on the Database Boot Page.&#160; Not sure which page that is?&#160; Well, there are 2 ways you can get to this information stored on it.</p>

<p>First, we can use DBCC DBINFO:</p>

<blockquote>
  <pre class="code"><span style="color: blue;">use </span><span style="color: teal;">scratchdb
</span><span style="color: blue;">go

dbcc </span><span style="color: teal;">traceon</span><span style="color: gray;">(</span>3604<span style="color: gray;">)
</span><span style="color: blue;">go

dbcc </span><span style="color: teal;">dbinfo</span><span style="color: gray;">()
</span><span style="color: blue;">go
</span></pre>
</blockquote>

<p>And we get our answers (results truncated):</p>

<pre class="csharpcode">DBCC execution completed. If DBCC printed error messages, contact your system administrator.

DBINFO STRUCTURE:


DBINFO @0x000000001A2DD520

dbi_dbid = 15                        dbi_status = 65536                   dbi_nextid = 2105058535
dbi_dbname = scratchdb               dbi_maxDbTimestamp = 2000            <font style="background-color: rgb(255, 255, 0);">dbi_version = 661</font>
dbi_createVersion = 661              dbi_ESVersion = 0                    
dbi_nextseqnum = 1900-01-01 00:00:00.000                                  <font style="background-color: rgb(255, 255, 0);">dbi_crdate = 2012-07-29 18:43:55.670</font>
dbi_filegeneration = 0               
dbi_checkptLSN

m_fSeqNo = 28                        m_blockOffset = 54                   m_slotId = 64
dbi_RebuildLogs = 0                  dbi_dbccFlags = 2                    
<font style="background-color: rgb(255, 255, 0);">dbi_dbccLastKnownGood = 1900-01-01 00:00:00.000</font>                           
dbi_dbbackupLSN

m_fSeqNo = 28                        m_blockOffset = 54                   m_slotId = 64

dbi_oldestBackupXactLSN

m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
<font style="background-color: rgb(255, 255, 0);">dbi_LastLogBackupTime = 2012-07-29 18:44:37.040</font>                           
dbi_differentialBaseLSN</pre>


<p>&#160;</p>

<p>Here you can see our information as well as the original database creation version, database status, it’s DB ID, and other information that is needed by SQL Server at startup when mounting a database.</p>

<p>So my database is version 661 (SQL Server 2008 R2 SP1), and the log was just backed up (and the database created just before that), and has never had DBCC CHECKDB run.&#160; As mentioned, this information is stored on the database boot page (pagetype 13).&#160; That is page #10 or ordinal position 9 starting from 0.&#160; You can find it with DBCC PAGE (the page will have just 1 slot for the DBINFO structure):</p>

<blockquote>
  <pre class="code"><span style="color: blue;">dbcc </span><span style="color: teal;">traceon</span><span style="color: gray;">(</span>3604<span style="color: gray;">)
</span><span style="color: blue;">go

dbcc page</span><span style="color: gray;">(</span>15<span style="color: gray;">, </span>1<span style="color: gray;">, </span>9<span style="color: gray;">, </span>3<span style="color: gray;">)
</span><span style="color: blue;">go
</span></pre>
</blockquote>

<pre class="csharpcode">DBCC execution completed. If DBCC printed error messages, contact your system administrator.

PAGE: (1:9)


BUFFER:


BUF @0x00000000B8FDBE80

bpage = 0x00000000B89FC000           bhash = 0x0000000000000000           bpageno = (1:9)
bdbid = 15                           breferences = 0                      bcputicks = 0
bsampleCount = 0                     bUse1 = 57609                        bstat = 0xc00009
blog = 0x89898989                    bnext = 0x0000000000000000           

PAGE HEADER:


Page @0x00000000B89FC000

m_pageId = (1:9)                     m_headerVersion = 1                 <font style="background-color: rgb(255, 255, 0);"> m_type = 13</font>
m_typeFlagBits = 0x0                 m_level = 0                          m_flagBits = 0x200
m_objId (AllocUnitId.idObj) = 99     m_indexId (AllocUnitId.idInd) = 0    Metadata: AllocUnitId = 6488064
Metadata: PartitionId = 0            Metadata: IndexId = 0                Metadata: ObjectId = 99
m_prevPage = (0:0)                   m_nextPage = (0:0)                   pminlen = 0
m_slotCnt = 1                        m_freeCnt = 6650                     m_freeData = 1540
m_reservedCnt = 0                    m_lsn = (28:85:3)                    m_xactReserved = 0
m_xdesId = (0:0)                     m_ghostRecCnt = 0                    m_tornBits = –223305262</pre>

<pre class="csharpcode"><font color="#ff0000">&lt;truncated&gt;</font></pre>

<pre class="csharpcode">DBINFO @0x000000001857A060

dbi_dbid = 15                        dbi_status = 65536                   dbi_nextid = 2105058535
dbi_dbname = scratchdb               dbi_maxDbTimestamp = 2000            dbi_version = 661
dbi_createVersion = 661              dbi_ESVersion = 0                    
dbi_nextseqnum = 1900-01-01 00:00:00.000                                  <font style="background-color: rgb(255, 255, 0);">dbi_crdate = 2012-07-29 18:43:55.670</font>
dbi_filegeneration = 0               
dbi_checkptLSN

m_fSeqNo = 28                        m_blockOffset = 54                   m_slotId = 64
dbi_RebuildLogs = 0                  dbi_dbccFlags = 2                    
<font style="background-color: rgb(255, 255, 0);">dbi_dbccLastKnownGood = 1900-01-01 00:00:00.000</font>                           
dbi_dbbackupLSN

m_fSeqNo = 28                        m_blockOffset = 54                   m_slotId = 64

dbi_oldestBackupXactLSN

m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
<font style="background-color: rgb(255, 255, 0);">dbi_LastLogBackupTime = 2012-07-29 18:44:37.040</font>                           
dbi_differentialBaseLSN</pre>

<p></p>

<p>-Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>Default Trace and System Health</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/default-trace-and-system-health</link>
      <pubDate>Thu, 28 Jun 2012 23:53:39 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2012/06/28/default-trace-and-system-health/</guid>
      <description><![CDATA[So it’s been a little while since my last posting – actually a long while.&#160; Since my last post...]]></description>
      <content:encoded><![CDATA[<p>So it’s been a little while since my last posting – actually a long while.&#160; Since my last post some 8 months ago I’ve changed customers in my role as a PFE here at Microsoft and that has had me quite busy.</p>  <p>I have a couple of posts I wanted to write to answer some questions I get from customers in our SQL Server Performance Tuning and Optimization Workshops – and to get back into updating my blog.&#160; So the question for this post:</p>  <p><em>Question:&#160; <u>What is captured by the default trace</u>?</em></p>  <p>This is actually a pretty simple question to answer if you know the right function to query in SQL Server – and you can undoubtedly find it by Binging it.&#160; However, I’m going to go ahead and outline it here combined with the system_health extended events trace – new starting in SQL Server 2008.</p>  <h3>SQL Trace Default Trace</h3>  <p>To get the events captured in SQL Server by the default trace, we just need to supply the trace id for the default trace to the fn_trace_geteventinfo function and join this to sys.trace_events to map the event id’s to their event names:</p>  <blockquote>   <p><font color="#ff0000" face="Courier New">declare @handle int = (select id from sys.traces where is_default = 1);        <br />select distinct e.eventid, n.name from         <br />&#160;&#160;&#160; fn_trace_geteventinfo(@handle) e         <br />&#160;&#160;&#160; join sys.trace_events n         <br />&#160;&#160;&#160; on e.eventid = n.trace_event_id         <br />&#160;&#160;&#160; order by n.name asc</font></p>  </blockquote>  <p>which gives us the event id and it’s event name captured by the default trace:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0385.image_2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0385.image_5F00_2.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/5661.image_thumb.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/5661.image_5F00_thumb.png" width="435" height="297" /></a></p>  <p>&#160;</p>  <p>if you wish to get the actual data out of the default trace files – there are 5 by default, then you can do the following to see what configuration and schema changes have been made on your system in the last 5 restarts of your SQL Service or in the last 100 MB of trace data – whichever comes first (the default trace automatically starts a new file at 20MB and maintains 5 files):</p>  <blockquote>   <p><font color="#ff0000" face="Courier New">declare @def_trace nvarchar(250) = (select path from sys.traces where is_default = 1)        <br />select e.name, x.* from&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; fn_trace_gettable(@def_trace, 5) x         <br />&#160;&#160;&#160; join sys.trace_events e         <br />&#160;&#160;&#160; on x.EventClass = e.trace_event_id</font></p>  </blockquote>  <p>&#160;</p>  <h3>System Health Extended Event Trace</h3>  <p>Starting with SQL Server 2008, we have a new tracing and diagnostic capability known as Extended Events.&#160; Extended Events is a much more robust way of collecting diagnostic and performance data on your SQL Server.&#160; It’s designed to be much more efficient when firing events.&#160; Additionally, filtering has been pushed down to the code level so that if the event doesn’t meet the criteria, it isn’t published. </p>  <p>In SQL Server 2008 you had to learn the syntax for creating Extended Event Sessions.&#160; The syntax isn’t bad, but the XPath style queries to process the results into rowsets is a bit tricky.&#160; In SQL Server 2012, we have a UI Wizard to help us perform these collections with ease:</p>  <p>&#160;</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/5672.image_4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/5672.image_5F00_4.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0871.image_thumb_1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0871.image_5F00_thumb_5F00_1.png" width="437" height="239" /></a></p>  <p>&#160;</p>  <p>In fact, SQL Trace is being deprecated in favor of Extended Events:</p>  <blockquote>   <p>Deprecated Database Engine Features in SQL Server 2012      <br /><a title="https://technet.microsoft.com/en-us/library/ms143729(SQL.110).aspx" href="https://technet.microsoft.com/en-us/library/ms143729(SQL.110).aspx">https://technet.microsoft.com/en-us/library/ms143729(SQL.110).aspx</a></p>  </blockquote>  <p>I don’t want to go into explaining how Extended Events work – or how to use them here.&#160; Virtual reams have already been written on those topics.&#160; Just know that in SQL Server 2012 the number of events has increased dramatically and it’s hard to imagine something you can’t capture using Extended Events.&#160;&#160; Jonathan Kehayias does a good job of explaining how to use Extended Events in a nice lesson-per-day format here:</p>  <blockquote>   <p>An XEvent A Day: 31 days of Extended Events      <br /><a title="https://sqlblog.com/blogs/jonathan_kehayias/archive/2010/12/01/a-xevent-a-day-31-days-of-extended-events.aspx" href="https://sqlblog.com/blogs/jonathan_kehayias/archive/2010/12/01/a-xevent-a-day-31-days-of-extended-events.aspx">https://sqlblog.com/blogs/jonathan_kehayias/archive/2010/12/01/a-xevent-a-day-31-days-of-extended-events.aspx</a></p>  </blockquote>  <p>In this post, I simply wanted to show you how to see which events are being captured in the new default system_health extended event session – much like the default trace above.&#160; You can see which sessions are active using:</p>  <blockquote>   <p><font color="#ff0000" face="Courier New">select * from sys.dm_xe_sessions</font></p>  </blockquote>  <p>Where you should see at least:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/8308.image_6.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/8308.image_5F00_6.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/7824.image_thumb_2.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/7824.image_5F00_thumb_5F00_2.png" width="662" height="59" /></a></p>  <p>&#160;</p>  <p>This new system_health extended events session is there to help product support troubleshooting basic, common performance problems.&#160; But what is it capturing?&#160; That information can be found using this query:</p>  <blockquote>   <p><font color="#ff0000" face="Courier New">select * from sys.dm_xe_session_events e        <br />&#160;&#160;&#160; inner join sys.dm_xe_sessions s         <br />&#160;&#160;&#160; on e.event_session_address = s.address</font></p>  </blockquote>  <p>which gives us:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0804.image_8.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0804.image_5F00_8.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/3531.image_thumb_3.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/3531.image_5F00_thumb_5F00_3.png" width="452" height="211" /></a></p>  <p>&#160;</p>  <p>Now some of these events have predicates for filtering what is captured.&#160; The predicate is used to filer what is captured so we don’t try to gather too much information – information that may not be useful to product support – like waits that aren’t common causes of performance problems.&#160; Extended event sessions have “targets” where they write their data to.&#160;&#160; The system_health session logs all data into a ring_buffer (and an event_file in SQL Server 2012 – called an asynchronous_file_target in SQL Server 2008).&#160; The ring_buffer is a circular buffer in memory that will wrap around and overwrite old records once it fills up.&#160; So how do you read the contents?&#160; Cast the data to XML and then extract it with an XPath query:</p>  <blockquote>   <p><font color="#ff0000" face="Courier New">declare @sys_health xml;</font></p>   <font color="#ff0000" face="Courier New"></font>    <p><font color="#ff0000" face="Courier New">set @sys_health = ( select cast(t.target_data as xml)        <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; from sys.dm_xe_session_targets t         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; join sys.dm_xe_sessions s         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; on t.event_session_address = s.address         <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; where s.name = 'system_health' )&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br /></font><font color="#ff0000" face="Courier New">       <br />select         <br />&#160;&#160;&#160; n.value('(@name)', 'nvarchar(50)') as [event name],         <br />&#160;&#160;&#160; n.value('(data[@name=&quot;wait_type&quot;]/text)[1]', 'nvarchar(50)') as wait_type,         <br />&#160;&#160;&#160; n.value('(data[@name=&quot;duration&quot;]/value)[1]', 'bigint') as duration,         <br />&#160;&#160;&#160; n.value('(action[@name=&quot;sql_text&quot;]/value)[1]', 'nvarchar(4000)') as stmt_text         <br />from @sys_health.nodes('/RingBufferTarget/event') as q(n)</font></p>  </blockquote>  <p>and on my server we get:</p>  <p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/7318.image_10.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/7318.image_5F00_10.png"><img style="display: inline; background-image: none;" title="image" border="0" alt="image" src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/29/59/metablogapi/0882.image_thumb_4.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-29-59-metablogapi/0882.image_5F00_thumb_5F00_4.png" width="714" height="90" /></a></p>  <p>-&#160; Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>How can I get a list of installed SQL Server instances?</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/how-can-i-get-a-list-of-installed-sql-server-instances</link>
      <pubDate>Tue, 11 Oct 2011 09:19:58 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2011/10/11/how-can-i-get-a-list-of-installed-sql-server-instances/</guid>
      <description><![CDATA[Today we’ll talk about how we can get a list of locally installed SQL Server instances on a...]]></description>
      <content:encoded><![CDATA[<p>Today we’ll talk about how we can get a list of locally installed SQL Server instances on a system.&#160;&#160; This information is stored in the registry at the following location:</p>  <blockquote>   <p><font color="#ff0000" face="Courier New">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL</font></p>    <p><font style="background-color: rgb(255, 255, 0);" color="#ff0000" face="Courier New"><strong>EDIT:</strong></font></p>    <p><font style="background-color: rgb(255, 255, 0);" color="#ff0000" face="Courier New">If you are looking for 32 bit instances on a 64 bit OS, you will need to look here:</font></p>    <p><font style="background-color: rgb(255, 255, 0);" color="#ff0000" face="Courier New">HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server\Instance Names\SQL</font></p>  </blockquote>  <p><font color="#000000">All we need to do is query this registry key to get the list of instances installed on a machine.&#160;&#160; On my personal machine, I have the following instances installed:</font></p>  <blockquote>   <p><font color="#ff0000" face="Courier New">SQLEXPRESS&#160;&#160;&#160; <br />MSSQLSERVER&#160;&#160;&#160; <br />CRASH&#160;&#160;&#160; <br />DEBUG&#160;&#160;&#160; <br />MICROSOFT##SSEE         <br />SQL2005</font>&#160;&#160; </p>  </blockquote>  <p>Below are a few ways we can get this information <em><u>for 64 bit instances on 64 bit Windows</u></em>:</p>  <p><strong></strong></p>  <p><strong>Command shell “reg.exe” utility:</strong></p>  <blockquote>   <p><font color="#ff0000" face="Courier New">reg query &quot;HKLM\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL&quot;</font></p>  </blockquote>  <p>&#160;</p>  <p><strong>In PowerShell:</strong></p>  <blockquote>   <p><font color="#ff0000" face="Courier New">Get-ItemProperty 'HKLM:\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL'</font></p>  </blockquote>  <p>&#160;</p>  <p><strong>In .NET:</strong></p>  <blockquote>   <p><font color="#ff0000" face="Courier New">RegistryKey baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);        <br />RegistryKey key = baseKey.OpenSubKey(@&quot;SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL&quot;);</font></p>   <font color="#ff0000" face="Courier New"></font>    <p><font color="#ff0000" face="Courier New">foreach (string s in key.GetValueNames())        <br />{         <br />&#160;&#160;&#160; MessageBox.Show(s);         <br />}</font></p>   <font color="#ff0000" face="Courier New"></font>    <p><font color="#ff0000" face="Courier New">key.Close();        <br />baseKey.Close();         <br /></font></p>  </blockquote>  <p>If you need to read the registry from another computer, then the RegistryKey class has a “OpenRemoteBaseKey” static method that you can use.&#160; </p>  <p>- Jay</p>]]></content:encoded>
    </item>
    <item>
      <title>Searching through the SQL Server Errorlogs</title>
      <link>https://docs.microsoft.com/archive/blogs/askjay/searching-through-the-sql-server-errorlogs</link>
      <pubDate>Mon, 10 Oct 2011 17:51:18 GMT</pubDate>
      <dc:creator><![CDATA[jamesask]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/askjay/2011/10/10/searching-through-the-sql-server-errorlogs/</guid>
      <description><![CDATA[Sorry – It’s been a while since my last post.&#160; The past few months have been very busy for...]]></description>
      <content:encoded><![CDATA[<p><font size="2" face="Arial">Sorry – It’s been a while since my last post.&#160; The past few months have been very busy for me.&#160; The other day, I had a brief discussion with a colleague on ways to search through all of the error logs in SQL Server.&#160; Obviously there are a few ways to do this – through PowerShell, simple Command/Batch Files, etc… Since I wrote an article on the parameters of xp_readerrorlog here:</font></p>  <p><font size="2" face="Arial">The Parameters of xp_readerrorlog</font>    <br /><a title="https://blogs.msdn.com/b/askjay/archive/2010/09/19/the-parameters-of-xp-readerrorlog.aspx" href="https://blogs.msdn.com/b/askjay/archive/2010/09/19/the-parameters-of-xp-readerrorlog.aspx"><font size="2" face="Arial">https://blogs.msdn.com/b/askjay/archive/2010/09/19/the-parameters-of-xp-readerrorlog.aspx</font></a></p>  <p><font size="2" face="Arial">I thought I’d go ahead and extend that methodology in a new post.&#160; A few things on this first…&#160; This is nice for DBAs because it’s likely to use the skills a DBA is already familiar with – namely TSQL.&#160; It also runs from within SQL Server instead of running a PowerShell or Batch File script from within the shell.&#160; However, just to be clear – we have announced that Extended Stored Procedures are being deprecated in SQL Server 2008 R2.&#160; For more information on this:</font></p>  <p><font size="2" face="Arial">Deprecated Database Engine Features in SQL Server 2008 R2     <br /></font><a title="https://msdn.microsoft.com/en-us/library/ms143729.aspx" href="https://msdn.microsoft.com/en-us/library/ms143729.aspx"><font size="2" face="Arial">https://msdn.microsoft.com/en-us/library/ms143729.aspx</font></a></p>  <p><font size="2" face="Arial">Work going forward should be done using CLR stored procedures.&#160; I do not know whether or not we’ll be providing a CLR replacement for this out of the box.&#160; If not, it would be a fairly simple procedure to write.     <br />      <br />With xp_readerrorlog, we can only read 1 error log at time by using the first parameter to specify the file extension and the second to specify whether we wish to read the SQL Server Errorlog or the SQL Agent Errorlog.&#160;&#160; To read all the logs – we just need to loop through reading all the logs and load them into a table (or return multiple result sets if we are ok with this).&#160;&#160; Below is a script that does just this:</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; if exists (select * from tempdb.sys.tables where name like '#Errorlog%')     <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; drop table #Errorlog;</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; create table #ErrorLog     <br />&#160;&#160;&#160; (      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; LogDate datetime,      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ProcessInfo nvarchar(16),      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; [Text] nvarchar(2048)      <br />&#160;&#160;&#160; )      <br />&#160;&#160;&#160; go</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; declare @p1 nvarchar(64);     <br />&#160;&#160;&#160; declare @p2 nvarchar(64);      <br />&#160;&#160;&#160; declare @logNum int;      <br />&#160;&#160;&#160; declare @NumErrorLogs int;</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; -- add search conditions here     <br />&#160;&#160;&#160; select @p1 = null;      <br />&#160;&#160;&#160; select @p2 = null;      <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; --get the value of max errorlogs from registry      <br />&#160;&#160;&#160; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'NumErrorLogs', @NumErrorLogs OUTPUT</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; -- init counter     <br />&#160;&#160;&#160; set @logNum = 0;</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; while (@logNum &lt;= @NumErrorLogs)     <br />&#160;&#160;&#160;&#160; begin      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; declare @exists int      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; exec xp_fileexist 'c:\windows\notepad.exe', @exists out      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (@exists = 1)      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; begin      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; insert into #Errorlog      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; exec xp_readerrorlog @logNum, 1, @p1, @p2      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; end      <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; select @logNum = (@logNum + 1);      <br />&#160;&#160;&#160;&#160; end</font></p>  <p><font color="#ff0000" size="2" face="Courier New">&#160;&#160;&#160; select * from #ErrorLog</font>    <br /></p>  <p><font size="2" face="Arial">Briefly, we check to see if the table exists, if it does DELETE it.&#160; Then create a temporary table to hold our executions of xp_readerrorlog.&#160; Next, we read the registry to get the configured max number of Errorlogs for our loop.&#160; Then we loop and load each execution into the temporary table.&#160; Once everything is in the temporary table we can obviously narrow down items further by adding a predicate to our SELECT statement.     <br />      <br />You could encounter a problem with this for servers that do not have all the log files configured by the maximum value set in SSMS.&#160; This situation would arise with new servers and with servers that have recently had this value increased.&#160; Therefore, with each loop we test to verify the file exists before attempting to execute xp_readerrorlog with xp_fileexist.      <br />      <br />Remember, there are many ways to accomplish this.&#160; I hope this is useful for those that like using xp_readerrorlog.      <br />      <br />-Jay</font></p>]]></content:encoded>
    </item>
  </channel>
</rss>