<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Randy Knight, Author at SQL Solutions Group</title>
	<atom:link href="https://sqlsolutionsgroup.com/author/rknight/feed/" rel="self" type="application/rss+xml" />
	<link>https://sqlsolutionsgroup.com/author/rknight/</link>
	<description></description>
	<lastBuildDate>Mon, 03 Aug 2026 20:53:57 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.3</generator>

<image>
	<url>https://sqlsolutionsgroup.com/wp-content/uploads/2021/01/cropped-SSG_FAVICON0002-32x32.png</url>
	<title>Randy Knight, Author at SQL Solutions Group</title>
	<link>https://sqlsolutionsgroup.com/author/rknight/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Table Variables, TVPs, and the One-Line CPU Fix</title>
		<link>https://sqlsolutionsgroup.com/table-variable-tvps-and-the-one-line-cpu-fix/</link>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Mon, 03 Aug 2026 08:57:55 +0000</pubDate>
				<category><![CDATA[SQL Server]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=8194</guid>

					<description><![CDATA[<p>Twice in the last two weeks I've been pulled into a "the server is pegged at 100% CPU and we don't know why" fire drill, and twice the fix turned out to be a single hint on one line of code.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/table-variable-tvps-and-the-one-line-cpu-fix/">Table Variables, TVPs, and the One-Line CPU Fix</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p dir="auto">Twice in the last two weeks I&#8217;ve been pulled into a &#8220;the server is pegged at 100% CPU and we don&#8217;t know why&#8221; fire drill, and twice the fix turned out to be a single hint on one line of code. Different clients, different applications, different schemas. Same root cause: a <strong>table variable</strong> — specifically, in both cases, one passed into a stored procedure as a <strong>table-valued parameter</strong>.</p>
<p dir="auto">Both teams had already been doing the sensible thing — running <code>UPDATE STATISTICS</code> on the tables involved — and this <em>sort of</em> worked &#8230; sometimes, for a while. That &#8220;sometimes, for a while&#8221; is the tell. When refreshing statistics gives you unpredictable, temporary relief, it usually means statistics were never the real problem.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">The Scenario</h2>
</div>
<p dir="auto">Picture a stored procedure that runs constantly — a polling job, an ETL step, a queue processor. The application hands it a batch of work as a table-valued parameter, and the proc uses that batch against a big table. Stripped down and anonymized:</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto">
<pre><span class="pl-c">-- The table type the TVP is built on</span>
<span class="pl-k">CREATE</span> <span class="pl-k">TYPE</span> <span class="pl-en">dbo</span>.KeyList <span class="pl-k">AS</span> TABLE
(
    KeyId <span class="pl-k">BIGINT</span> <span class="pl-k">PRIMARY KEY</span>
);
GO

CREATE <span class="pl-k">OR</span> ALTER PROC <span class="pl-c1">dbo</span>.<span class="pl-c1">usp_DoSomething</span>
    @Work <span class="pl-c1">dbo</span>.<span class="pl-c1">KeyList</span> READONLY      <span class="pl-c">-- some runs pass 12 rows, some pass 40,000</span>
<span class="pl-k">AS</span>
<span class="pl-k">BEGIN</span>
    <span class="pl-k">DELETE</span> t
    <span class="pl-k">FROM</span> <span class="pl-c1">dbo</span>.<span class="pl-c1">BigEventTable</span> <span class="pl-k">AS</span> t
    <span class="pl-k">JOIN</span> @Work <span class="pl-k">AS</span> w <span class="pl-k">ON</span> <span class="pl-c1">w</span>.<span class="pl-c1">KeyId</span> <span class="pl-k">=</span> <span class="pl-c1">t</span>.<span class="pl-c1">KeyId</span>
    <span class="pl-k">WHERE</span> <span class="pl-c1">t</span>.<span class="pl-c1">CompletedDate</span> <span class="pl-k">IS NOT NULL</span>;
END;</pre>
</div>
<p dir="auto">Most of the time it runs in milliseconds. Then, seemingly at random, CPU slams to 100% and stays there, alerts fire off, and somebody connects and runs <code>UPDATE STATISTICS</code> (or restarts the app, or clears the cache). CPU drops. Everybody exhales. Then it happens again.</p>
<p dir="auto">Here&#8217;s the thing: the data didn&#8217;t change in any meaningful way, the indexes are fine, and your statistics were never stale. The problem is the <code>@Work</code> table variable and how SQL Server estimates the number of rows in it.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">What&#8217;s Actually Happening?</h2>
</div>
<p dir="auto">Every table variable — whether you <code>DECLARE</code> one locally or receive it as a table-valued parameter — shares one root limitation: <strong>it carries no column-level statistics.</strong> There&#8217;s no histogram telling the optimizer how the values are distributed. It&#8217;s flying blind on everything except, at best, the raw row count. And how it estimates <em>that</em> count depends on which flavor you&#8217;re using.</p>
<h4 dir="auto"><strong>Local table variables (<code>DECLARE @x TABLE</code>).</strong></h4>
<p dir="auto">Before SQL Server 2019, the optimizer simply guessed <strong>one row</strong>, every time. Estimate one row, build a plan for one row — usually a nested loop — then watch it fall over when 40,000 rows show up. SQL Server 2019 at <strong>compatibility level 150</strong> improved this with <strong>Table Variable Deferred Compilation</strong>: it waits until the variable is populated, then compiles using the real count. Genuine improvement — but it sets that estimate <strong>once, at first compilation, and caches the plan.</strong> It does not recompile every execution.</p>
<h4 dir="auto"><strong>Table-valued parameters (<code>@x dbo.SomeType READONLY</code>).</strong></h4>
<p dir="auto">This is the flavor that bit my clients. Because a TVP is materialized by the caller <em>before</em> the statement compiles, the optimizer has known the true row count since TVPs shipped in 2008 — they never had the one-row guess. But that accurate count is captured at the <strong>first</strong> compile and baked into the <strong>cached plan</strong>, exactly like a sniffed parameter value.</p>
<p dir="auto">See the common thread? Whichever flavor you use, you land in the same place: <strong>a plan compiled for one row count, then reused for a wildly different one.</strong></p>
<ul dir="auto">
<li>The proc first compiles on a run where <code>@Work</code> holds 12 rows → SQL Server caches a tidy nested-loop plan.</li>
<li>A later run passes 40,000 rows and reuses that cached small-batch plan.</li>
<li>The nested loop seeks into <code>dbo.BigEventTable</code> 40,000 times, and there&#8217;s your CPU.</li>
</ul>
<p dir="auto">That also explains the maddening &#8220;<code>UPDATE STATISTICS</code> fixed it&#8221; experience. The table variable has no statistics to update, so the script wasn&#8217;t correcting anything the optimizer uses for <code>@Work</code>. What it <em>was</em> doing — as a side effect — is invalidating the cached plan and forcing a recompile. Land that recompile on a big-batch run and you get a good plan; land it on a small batch and you re-cache the bad one. It&#8217;s a coin flip dressed up as a fix.</p>
<p dir="auto">To confirm it, pull the actual execution plan and look at the operator reading the table variable. If <strong>Estimated Number of Rows</strong> is wildly smaller than <strong>Actual</strong> (literally <code>1</code> on a pre-2019 local variable, or the stale first-compile count on a TVP), you&#8217;ve found it. On a busy server, Query Store will usually be flagging the same statement as a top CPU consumer with more than one plan on file.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">The Fix: One Line</h2>
</div>
<p dir="auto">Append a statement-level hint:</p>
<div class="highlight highlight-source-sql notranslate position-relative overflow-auto" dir="auto">
<pre><span class="pl-k">DELETE</span> t
<span class="pl-k">FROM</span> <span class="pl-c1">dbo</span>.<span class="pl-c1">BigEventTable</span> <span class="pl-k">AS</span> t
<span class="pl-k">JOIN</span> @Work <span class="pl-k">AS</span> w <span class="pl-k">ON</span> <span class="pl-c1">w</span>.<span class="pl-c1">KeyId</span> <span class="pl-k">=</span> <span class="pl-c1">t</span>.<span class="pl-c1">KeyId</span>
<span class="pl-k">WHERE</span> <span class="pl-c1">t</span>.<span class="pl-c1">CompletedDate</span> <span class="pl-k">IS NOT NULL</span>
OPTION (RECOMPILE);</pre>
</div>
<p dir="auto"><code>OPTION (RECOMPILE)</code> tells SQL Server to recompile <strong>just this statement, on every execution,</strong> using the actual row count of <code>@Work</code> at that moment. Twelve rows tonight, forty thousand tomorrow — it builds the right plan each time. It&#8217;s the reliable, deterministic version of the recompile your <code>UPDATE STATISTICS</code> script was triggering by accident, and it works the same for a local table variable or a TVP.</p>
<p dir="auto">What makes it the right first move: it&#8217;s <strong>surgical</strong> (scoped to one statement — the rest of the proc&#8217;s plan stays cached), it&#8217;s <strong>logic-neutral</strong> (you&#8217;re changing how the statement compiles, not what it does, which makes it an easy sell on vendor code), and the per-execution compile cost is trivial next to a runaway nested loop pinning every core. In both of my recent cases, CPU dropped from sustained 90%-plus back to normal within minutes — no index rebuild, no schema change, no restart.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">&#8220;So Should I Just Use a Temp Table?&#8221;</h2>
</div>
<p dir="auto">Often, yes. A temporary table (<code>#Work</code>) carries real statistics — including a histogram — and participates in normal recompilation thresholds, fixing the estimate at the source. If the batch is genuinely variable and feeds joins against big tables, a <code>#temp</code> table is frequently the better long-term answer; a common pattern is to copy a TVP into a <code>#temp</code> at the top of the proc precisely so the optimizer gets real statistics. So why reach for the hint first? Because it&#8217;s the smallest possible change. When I&#8217;m putting out a fire on someone else&#8217;s code at 11 PM, &#8220;add one line&#8221; beats &#8220;refactor the procedure.&#8221; Ship the hint to stop the bleeding, then propose the temp-table refactor as the permanent fix.</p>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Gotchas</h2>
</div>
<ul dir="auto">
<li><strong>It&#8217;s per-execution.</strong> If the statement runs hundreds of times <em>per second</em>, the cumulative compile cost can become its own problem. For a periodic batch or polling job it&#8217;s a non-issue; for a hot OLTP path, prefer the temp-table route.</li>
<li><strong>Keep functions off your join columns.</strong> In one case the join also wrapped the key in <code>ABS()</code> — <code>ON ABS(w.KeyId) = t.KeyId</code>. A function on the column is non-SARGable and kills index seeks. Fixing the estimate solved the CPU, but that was a second sin worth cleaning up.</li>
<li><strong>Don&#8217;t confuse it with <code>WITH RECOMPILE</code> on the procedure.</strong> Statement-level <code>OPTION (RECOMPILE)</code> recompiles one statement (and can use actual parameter values too); procedure-level <code>WITH RECOMPILE</code> throws away the entire plan on every call.</li>
</ul>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">Lessons Learned</h2>
</div>
<ul dir="auto">
<li>When <code>UPDATE STATISTICS</code> gives you unreliable, temporary relief, stop updating statistics and ask <em>why a recompile helps.</em> The answer is often a table variable or a TVP.</li>
<li>Neither carries column statistics. Local variables misestimate the count (one-row guess pre-2019; cached first estimate after); TVPs get the count right but cache it from the first call. Different routes, same cliff.</li>
<li>Reserve both for what they&#8217;re good at — small, predictable row counts and passing modest sets between tiers. The moment one carries thousands of rows into a join against a big table, it&#8217;s the wrong tool; copy it into a temp table.</li>
</ul>
<div class="markdown-heading" dir="auto">
<h2 class="heading-element" dir="auto" tabindex="-1">The Final Word</h2>
<p>This is why DBAs get twitchy about table variables and TVPs. They&#8217;re not evil — they&#8217;re a fine, lightweight choice for small sets, and I use them all the time. But they quietly lie to the optimizer about what they hold, and on a busy system that lie eventually gets expensive. Use them judiciously, know how many rows you expect them to carry, and when one surprises you with a CPU spike that statistics won&#8217;t fix, you now know where to look — and that the fix might be one line long.</p>
</div>
<hr />
<p dir="auto"><em>Chasing an intermittent CPU problem that &#8220;fixes itself&#8221; and then comes right back? <a href="https://sqlsolutionsgroup.com/" rel="nofollow">SQL Solutions Group</a> has spent years running these down for clients — we&#8217;re happy to help you find the one line of code that&#8217;s lighting up your server.</em></p>
<p>The post <a href="https://sqlsolutionsgroup.com/table-variable-tvps-and-the-one-line-cpu-fix/">Table Variables, TVPs, and the One-Line CPU Fix</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Intermittent &#8220;Cannot Generate SSPI Context&#8221; in SQL Server? Here&#8217;s the 2022 Kerberos Trap (and How to Fix It)</title>
		<link>https://sqlsolutionsgroup.com/intermittent-cannot-generate-sspi-context/</link>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Wed, 10 Jun 2026 16:20:34 +0000</pubDate>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[#Kerberos #SSPI #SQLServer #SQLTraining]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=7658</guid>

					<description><![CDATA[<p>Windows logins to a SQL Server AG started throwing "Cannot generate SSPI context" — but only sometimes, and only for some people. We solve it.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/intermittent-cannot-generate-sspi-context/">Intermittent &#8220;Cannot Generate SSPI Context&#8221; in SQL Server? Here&#8217;s the 2022 Kerberos Trap (and How to Fix It)</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3><strong>Overview</strong></h3>
<p>We recently had a customer where Windows logins to a SQL Server Availability Group started throwing &#8220;Cannot generate SSPI context&#8221; — but only sometimes, and only for some people. The same user, on the same workstation, would fail one minute and connect the next. Applications were fine. Nothing had changed on SQL Server.</p>
<p>It took the better part of two days and a lot of second-guessing to run down, and the culprit turned out to be something most of us never think about: <em>which domain controller handed out the Kerberos ticket.</em></p>
<p>In the spirit of full disclosure, I burned most of the first day chasing the usual SPN suspects before the real cause showed itself. <span style="color: #f25e00;"><strong>So let me save you that day</strong></span>.</p>
<p>Here&#8217;s what we&#8217;ll cover:</p>
<ul>
<li>Why a healthy SQL Server starts failing Windows auth for some users and not others</li>
<li>How to prove it&#8217;s the domain controllers, not your SPNs</li>
<li>The interim fix (no restart) and the permanent one</li>
</ul>
<h3><strong>The Scenario</strong></h3>
<p>Two-node Always On AG, Windows authentication, and an intermittent <em>&#8220;The target principal name is incorrect. Cannot generate SSPI context.&#8221;</em> The pattern that makes you question your sanity:</p>
<ul>
<li>Same user, same machine — works, then fails, then works.</li>
<li>Fails from some client machines, succeeds from others, with no obvious pattern.</li>
<li>Applications connect fine; only interactive users (SSMS, Visual Studio Code) hit it.</li>
<li>No failover, no deploy, no SPN changes.</li>
</ul>
<p>Everything you&#8217;d normally check comes back clean. The SPNs are registered correctly. No duplicates. The service account is right on every node. By every test you&#8217;ve ever used, this should work — <strong>and half the time, it does</strong>.</p>
<h3><strong>What&#8217;s Actually Happening?</strong></h3>
<p>Here&#8217;s the thing: this isn&#8217;t an SPN problem at all. It&#8217;s an <em>encryption-type</em> problem, and it&#8217;s a delayed gift from the November 2022 Kerberos hardening updates (CVE-2022-37966 / KB5021131).</p>
<p>A quick refresher: When you authenticate to SQL Server over Kerberos, a domain controller hands you a ticket encrypted with the SQL <strong>service account&#8217;s</strong> key. Historically that was <strong>RC4</strong>. Microsoft has been pushing everyone to <strong>AES</strong>, and an account can hold keys for both. Which type a DC issues depends on the account&#8217;s msDS-SupportedEncryptionTypes attribute.</p>
<p>Before November 2022, DCs would quietly fill in RC4/AES support for any account that hadn&#8217;t declared one. That update <strong>stopped</strong> that. Now, if an account&#8217;s msDS-SupportedEncryptionTypes is <strong>null</strong> — and most service accounts have never had it set — each DC falls back to its own DefaultDomainSupportedEncTypes registry setting, which depends on <em>that DC&#8217;s</em> patch level and configuration.</p>
<p>In a shop with more than a couple of DCs patched on different schedules by different hands, <span style="color: #f25e00;"><strong>that&#8217;s the trap</strong></span>: one DC issues AES, another issues RC4. If the account&#8217;s AES key happens to be unusable — a salt mismatch, a stale key — the AES tickets fail and the RC4 tickets work. And since a client doesn&#8217;t choose its domain controller, whether your connection succeeds is a coin flip. <em>That</em> is your &#8220;comes and goes.&#8221;</p>
<h3><strong>How to Prove It</strong></h3>
<p>This is the move that finally cracked it for us, and it&#8217;s the first one to reach for next time. Pick a client that <strong>fails</strong> and one that <strong>works</strong>, and ask each to fetch a ticket for the same SQL SPN:</p>
<div id="wpshdo_1" class="wp-synhighlighter-outer"><div id="wpshdt_1" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_1"></a><a id="wpshat_1" class="wp-synhighlighter-title" href="#codesyntax_1"  onClick="javascript:wpsh_toggleBlock(1)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_1" onClick="javascript:wpsh_code(1)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_1" onClick="javascript:wpsh_print(1)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_1" class="wp-synhighlighter-inner" style="display: block;"><pre class="tsql" style="font-family:monospace;">klist purge
klist <span class="kw1">GET</span> MSSQLSvc<span class="sy0">/</span>sqlnode1.<span class="me1">contoso</span>.<span class="me1">com</span>
klist</pre></div></div>
<p>On the <strong>working</strong> client:</p>
<p style="padding-left: 40px;">Server: MSSQLSvc/sqlnode1.contoso.com @ CONTOSO.COM<br />
KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)<br />
Kdc Called: DC02.contoso.com</p>
<p>On the <strong>failing</strong> client — same SPN, same account:</p>
<p style="padding-left: 40px;">Server: MSSQLSvc/sqlnode1.contoso.com @ CONTOSO.COM<br />
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96<br />
Kdc Called: DC01.contoso.com</p>
<p>Read that twice. One client got RC4 from DC02 (works), the other got AES from DC01 (fails). The <strong>encryption type</strong> of the ticket — and the <strong>DC that issued it</strong> — is the entire story, and no SPN tool will ever show it to you.</p>
<p>While you&#8217;re there, confirm what each DC is doing and rule out the things it <em>isn&#8217;t</em>:</p>
<div id="wpshdo_2" class="wp-synhighlighter-outer"><div id="wpshdt_2" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_2"></a><a id="wpshat_2" class="wp-synhighlighter-title" href="#codesyntax_2"  onClick="javascript:wpsh_toggleBlock(2)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_2" onClick="javascript:wpsh_code(2)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_2" onClick="javascript:wpsh_print(2)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_2" class="wp-synhighlighter-inner" style="display: block;"><pre class="tsql" style="font-family:monospace;"># account: null enctype <span class="sy0">+</span> <span class="kw1">OLD</span><span class="sy0">/</span>consistent password rules <span class="kw1">OUT</span> a recent reset
&nbsp;
<span class="st0">'DC01'</span>,<span class="st0">'DC02'</span> <span class="sy0">|</span> ForEach<span class="sy0">-</span><span class="kw1">OBJECT</span> <span class="br0">&#123;</span>
&nbsp;
Get<span class="sy0">-</span>ADUser svc_sql <span class="sy0">-</span>Properties msDS<span class="sy0">-</span>SupportedEncryptionTypes,pwdLastSet <span class="sy0">-</span>Server $_ <span class="sy0">|</span>
&nbsp;
Select<span class="sy0">-</span><span class="kw1">OBJECT</span> @<span class="br0">&#123;</span>n<span class="sy0">=</span><span class="st0">'DC'</span>;e<span class="sy0">=</span><span class="br0">&#123;</span>$_<span class="br0">&#125;</span><span class="br0">&#125;</span>, msDS<span class="sy0">-</span>SupportedEncryptionTypes
&nbsp;
<span class="br0">&#125;</span>
&nbsp;
repadmin <span class="sy0">/</span>replsummary # 0 failures <span class="sy0">=</span> not a <span class="kw1">REPLICATION</span> problem</pre></div></div>
<p>Null enctype, a consistent (old) password, zero replication failures, and two DCs handing out different ticket types is the fingerprint.</p>
<h3><strong>Resolution</strong></h3>
<p>There are two fixes, and which you reach for depends on whether you can take a maintenance window.</p>
<h4><strong>The no-restart interim fix</strong></h4>
<p>Pin the account to RC4 so every DC issues the ticket that already works:</p>
<div id="wpshdo_3" class="wp-synhighlighter-outer"><div id="wpshdt_3" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_3"></a><a id="wpshat_3" class="wp-synhighlighter-title" href="#codesyntax_3"  onClick="javascript:wpsh_toggleBlock(3)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_3" onClick="javascript:wpsh_code(3)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_3" onClick="javascript:wpsh_print(3)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_3" class="wp-synhighlighter-inner" style="display: block;"><pre class="tsql" style="font-family:monospace;">Set<span class="sy0">-</span>ADUser svc_sql <span class="sy0">-</span><span class="kw2">REPLACE</span> @<span class="br0">&#123;</span><span class="st0">'msDS-SupportedEncryptionTypes'</span><span class="sy0">=</span>4<span class="br0">&#125;</span> # 4 <span class="sy0">=</span> RC4 <span class="kw1">ONLY</span></pre></div></div>
<p>It&#8217;s a settings-only change, it replicates in seconds, and it restores service across the board without touching SQL Server. Now, pinning to RC4 sounds like <em>exactly the wrong direction</em> given that RC4 is what these updates are retiring. And it is, as a <em>permanent</em> answer. But as a <strong>bridge</strong>, it&#8217;s the right call: it&#8217;s deterministic, it needs no downtime, and it buys you the window to do the real fix. Don&#8217;t leave it there forever, and resist the urge to set RC4-plus-AES (0x1C) — the DC will still prefer the broken AES and you&#8217;ll be right back where you started.</p>
<h4><strong>The permanent fix</strong></h4>
<p>When you can take a brief SQL restart:</p>
<ol>
<li><strong>Reset the service account password and restart the SQL Server service.</strong> This regenerates a correct AES key that the running service and the DCs agree on.</li>
<li><strong>Set the account explicitly to AES</strong> so every DC issues the same thing: <div id="wpshdo_4" class="wp-synhighlighter-outer"><div id="wpshdt_4" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_4"></a><a id="wpshat_4" class="wp-synhighlighter-title" href="#codesyntax_4"  onClick="javascript:wpsh_toggleBlock(4)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_4" onClick="javascript:wpsh_code(4)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_4" onClick="javascript:wpsh_print(4)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_4" class="wp-synhighlighter-inner" style="display: block;"><pre class="tsql" style="font-family:monospace;">Set<span class="sy0">-</span>ADUser svc_sql <span class="sy0">-</span><span class="kw2">REPLACE</span> @<span class="br0">&#123;</span><span class="st0">'msDS-SupportedEncryptionTypes'</span><span class="sy0">=</span><span class="nu0">24</span><span class="br0">&#125;</span> <span class="br0">&#40;</span><span class="nu0">24</span> <span class="sy0">=</span> AES128 <span class="sy0">+</span> AES256<span class="br0">&#41;</span></pre></div></div></li>
<li><strong>Get your domain controllers consistent</strong> — same patch level, same DefaultDomainSupportedEncTypes. This one&#8217;s domain-wide hygiene; the same trap is waiting on your <em>other</em> service accounts as RC4 gets disabled.</li>
</ol>
<h3><strong>Gotchas</strong></h3>
<p>A few things make this especially nasty on SQL Server:</p>
<ul>
<li><strong>NTLM fallback lies to you.</strong> Many SQL connections silently fall back to NTLM, so most users &#8220;work&#8221; while Kerberos is quietly broken. Don&#8217;t trust &#8220;it connects&#8221; — check auth_scheme in sys.dm_exec_connections. The boxes that fail loudest are often locked-down admin jump boxes that <em>can&#8217;t</em> fall back, which makes them your honest canary.</li>
<li><strong>Connection pooling masks it.</strong> A reused pooled connection reports whoever opened it. Probe with pooling off.</li>
<li><strong>It cascades into double-hops.</strong> SSRS, linked servers, anything delegated rides on top of this. If the first hop can&#8217;t do Kerberos, no amount of delegation config saves you. Don&#8217;t go down that road until single-hop Kerberos is solid.</li>
</ul>
<h3><strong>Lessons Learned</strong></h3>
<ul>
<li>Intermittent SSPI that tracks the <em>source machine</em> or the <em>DC</em>, not the target, is an encryption-type problem — not an SPN problem. Stop editing SPNs.</li>
<li>klist&#8217;s <strong>KerbTicket Encryption Type</strong> and <strong>Kdc Called</strong> are the two lines that matter.</li>
<li>Explicitly set msDS-SupportedEncryptionTypes on your service accounts. Relying on the null default is what turned a dormant issue into a landmine.</li>
<li>Keep your DCs consistent. Authentication that depends on luck isn&#8217;t authentication.</li>
</ul>
<h3><strong>Final Word</strong></h3>
<p>The RC4 pin can feel like giving up — you&#8217;re deliberately stepping onto the protocol Microsoft is trying to kill. But used the way we used it here, as a no-downtime bridge to a proper AES fix, it&#8217;s exactly the right move: it stops the bleeding today and gives you room to do it right on your schedule.</p>
<p>If you&#8217;d rather not spend two days proving this out on your own AG, <a href="https://sqlsolutionsgroup.com/">SQL Solutions Group</a> has been untangling SQL Server high-availability and authentication gremlins for years. We&#8217;re always glad to help!</p>
<p>The post <a href="https://sqlsolutionsgroup.com/intermittent-cannot-generate-sspi-context/">Intermittent &#8220;Cannot Generate SSPI Context&#8221; in SQL Server? Here&#8217;s the 2022 Kerberos Trap (and How to Fix It)</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Group Managed Service Accounts and SQL Server: What You Actually Need to Know</title>
		<link>https://sqlsolutionsgroup.com/group-managed-service-accounts/</link>
					<comments>https://sqlsolutionsgroup.com/group-managed-service-accounts/#comments</comments>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Fri, 01 May 2026 14:33:39 +0000</pubDate>
				<category><![CDATA[SQL Group]]></category>
		<category><![CDATA[SQL Server]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=7479</guid>

					<description><![CDATA[<p>Service account management is one of the quietest ways a SQL Server estate goes wrong. Passwords get set once during install, written down somewhere (or worse, not written down), and then never rotated. The DBA who built the environment leaves. A security audit shows up. Suddenly you&#8217;re staring at a hundred service account passwords nobody [&#8230;]</p>
<p>The post <a href="https://sqlsolutionsgroup.com/group-managed-service-accounts/">Group Managed Service Accounts and SQL Server: What You Actually Need to Know</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Service account management is one of the quietest ways a SQL Server estate goes wrong. Passwords get set once during install, written down somewhere <em>(or worse, not written down)</em>, and then never rotated. The DBA who built the environment leaves. A security audit shows up. Suddenly you&#8217;re staring at a hundred service account passwords nobody remembers, and the prospect of changing them all on a maintenance window nobody wants to schedule. <span style="color: #f25e00;"><strong>Group Managed Service Accounts (gMSAs) solve this</strong></span>.</p>
<p>They&#8217;ve been a fully supported option for SQL Server since 2014, they work with Failover Cluster Instances and Availability Groups, and Active Directory rotates the passwords for you on a schedule you control. We use them by default on every new SQL Server build at SSG.</p>
<p>And yet, in a decade of Health Checks, we still rarely see them deployed. The most common reasons we hear: &#8220;I tried it once and SPNs broke,&#8221; or, &#8220;I wasn&#8217;t sure it would work with our AG.&#8221; Both are addressable. Here&#8217;s what you need to know to deploy gMSAs successfully.</p>
<h3>Why gMSAs Win</h3>
<p>A gMSA is an Active Directory account whose password is generated by the Key Distribution Service (KDS), rotated automatically (default every 30 days), and retrievable only by computer accounts you explicitly authorize. That gives you four things:</p>
<ul>
<li><strong>Passwords you don&#8217;t know, can&#8217;t leak, and can&#8217;t forget to rotate</strong>. The password is 240 bytes of cryptographic randomness. No human ever sees it.</li>
<li><strong>No service restart on rotation</strong>. When AD rotates the password, the SQL Server service keeps running. This is the part most people don&#8217;t believe until they see it.</li>
<li><strong>Automatic SPN management</strong>. The account can register and update its own Service Principal Names, eliminating one of the most painful manual chores in Kerberos troubleshooting.</li>
<li><strong>Cluster-aware</strong>. Unlike standalone Managed Service Accounts (sMSAs), a gMSA can be used by multiple computers, which means it works for Failover Cluster Instances and Availability Group replicas.</li>
</ul>
<p>If you&#8217;re still managing SQL Server service accounts as regular AD user accounts with a 90-day password expiry policy and a coordinated change window, you&#8217;re doing work that <span style="color: #f25e00;"><strong>AD will do for you free</strong></span>.</p>
<h3>Prerequisites</h3>
<p>Before you create your first gMSA, the domain needs a KDS root key. This is a one-time, domain-wide setup step. By default, AD enforces a 10-hour wait after key creation before the key becomes usable, which is a safety mechanism to ensure replication completes across all domain controllers.</p>
<div id="wpshdo_5" class="wp-synhighlighter-outer"><div id="wpshdt_5" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_5"></a><a id="wpshat_5" class="wp-synhighlighter-title" href="#codesyntax_5"  onClick="javascript:wpsh_toggleBlock(5)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_5" onClick="javascript:wpsh_code(5)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_5" onClick="javascript:wpsh_print(5)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_5" class="wp-synhighlighter-inner" style="display: block;"><pre class="powershell" style="font-family:monospace;"><span class="co1"># On a domain controller (or any machine with AD module)</span>
<span class="co1"># Production: just run this and wait 10 hours</span>
Add<span class="sy0">-</span>KdsRootKey <span class="sy0">-</span>EffectiveImmediately
&nbsp;
<span class="co1"># Lab/test only: bypass the 10-hour wait</span>
Add<span class="sy0">-</span>KdsRootKey <span class="sy0">-</span>EffectiveTime <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw1">Get-Date</span><span class="br0">&#41;</span>.AddHours<span class="br0">&#40;</span><span class="sy0">-</span><span class="nu0">10</span><span class="br0">&#41;</span><span class="br0">&#41;</span></pre></div></div>
<p>&nbsp;</p>
<p>Verify a key exists before proceeding:</p>
<div id="wpshdo_6" class="wp-synhighlighter-outer"><div id="wpshdt_6" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_6"></a><a id="wpshat_6" class="wp-synhighlighter-title" href="#codesyntax_6"  onClick="javascript:wpsh_toggleBlock(6)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_6" onClick="javascript:wpsh_code(6)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_6" onClick="javascript:wpsh_print(6)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_6" class="wp-synhighlighter-inner" style="display: block;"><pre class="powershell" style="font-family:monospace;">Get<span class="sy0">-</span>KdsRootKey</pre></div></div>
<p>You also need:</p>
<ul>
<li>Windows Server 2012 or higher on the SQL Server hosts (we strongly recommend 2019+)</li>
<li>SQL Server 2014 or higher (every supported version qualifies)</li>
<li>The RSAT Active Directory PowerShell module on whichever machine you&#8217;re using to create the accounts</li>
</ul>
<h3>Account Structure: One Per Service, Per Server (Mostly)</h3>
<p>The pattern we deploy at SSG: a separate gMSA for each SQL Server service <em>type</em> (Database Engine, SQL Agent, SSRS, SSAS) on each standalone server. For clustered services — FCIs and AG replicas — we use a single gMSA shared across all nodes in that cluster.</p>
<p>Why separate accounts per service type? Least privilege. Your SQL Agent account often needs different rights than your Database Engine account (proxy operations, file system access for job output, etc.). Putting them on the same account means you grant the union of all permissions to both, which is exactly what we&#8217;re trying to avoid.</p>
<p>Why a single account across cluster nodes? Because all nodes need to authenticate as the same identity to the network. The whole point of an FCI or AG is that clients connect to a virtual name that can move; the underlying service identity must be consistent.</p>
<p>A naming convention that holds up over time:</p>
<table>
<thead>
<tr>
<th><strong>Service</strong></th>
<th><strong>Standalone</strong></th>
<th><strong>Clustered (FCI/AG)</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Database Engine</td>
<td>SQLEng_&lt;server&gt;</td>
<td>SQLEng_&lt;cluster&gt;</td>
</tr>
<tr>
<td>SQL Agent</td>
<td>SQLAgent_&lt;server&gt;</td>
<td>SQLAgent_&lt;cluster&gt;</td>
</tr>
<tr>
<td>SSRS / SSAS</td>
<td>SSRS_&lt;server&gt;</td>
<td>SSAS_&lt;cluster&gt;</td>
</tr>
</tbody>
</table>
<p><span style="color: #f25e00;"><strong>Heads up</strong></span>: gMSA sAMAccountName is capped at 15 characters (with a $ suffix that AD adds automatically). Long server names will collide with this. Plan your naming convention before you start creating accounts. That is why the suggested naming convention above does not have a lot of extra fluff like gmsa_svc_sql_&lt;server&gt; or the like. Every gmsa account will have a $ at the end so that’s how it is clear that it is a service account and is a gmsa.</p>
<h3>Creating the Account</h3>
<p>Two-step process: create an AD security group containing the computer accounts that will use the gMSA, then create the gMSA itself referencing that group. The security group is the indirection layer that makes gMSAs cluster-friendly — adding a new node to an FCI or AG later means adding its computer account to the group, not creating a new gMSA.</p>
<div id="wpshdo_7" class="wp-synhighlighter-outer"><div id="wpshdt_7" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_7"></a><a id="wpshat_7" class="wp-synhighlighter-title" href="#codesyntax_7"  onClick="javascript:wpsh_toggleBlock(7)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_7" onClick="javascript:wpsh_code(7)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_7" onClick="javascript:wpsh_print(7)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_7" class="wp-synhighlighter-inner" style="display: block;"><pre class="powershell" style="font-family:monospace;"><span class="co1"># 1. Create the security group, add computer accounts</span>
New<span class="sy0">-</span>ADGroup <span class="kw5">-Name</span> <span class="st0">'gsg_SQL_PRODAG01'</span> \
    <span class="sy0">-</span>GroupScope Global <span class="sy0">-</span>GroupCategory Security \
    <span class="kw5">-Path</span> <span class="st0">'OU=Service Groups,DC=contoso,DC=com'</span>
&nbsp;
Add<span class="sy0">-</span>ADGroupMember <span class="sy0">-</span>Identity <span class="st0">'gsg_SQL_PRODAG01'</span> \
    <span class="sy0">-</span>Members <span class="st0">'SQLNODE01$'</span><span class="sy0">,</span><span class="st0">'SQLNODE02$'</span><span class="sy0">,</span><span class="st0">'SQLNODE03$'</span>
&nbsp;
<span class="co1"># 2. Create the gMSA</span>
New<span class="sy0">-</span>ADServiceAccount <span class="kw5">-Name</span> <span class="st0">'SQLEng_PRODAG01'</span> \
    <span class="sy0">-</span>DNSHostName <span class="st0">'PRODAG01.contoso.com'</span> \
    <span class="sy0">-</span>PrincipalsAllowedToRetrieveManagedPassword <span class="st0">'gsg_SQL_PRODAG01'</span> \
    <span class="sy0">-</span>ManagedPasswordIntervalInDays <span class="nu0">30</span> \
    <span class="sy0">-</span>ServicePrincipalNames <span class="sy0">@</span><span class="br0">&#40;</span>
        <span class="st0">'MSSQLSvc/PRODAG01.contoso.com'</span><span class="sy0">,</span>
        <span class="st0">'MSSQLSvc/PRODAG01.contoso.com:1433'</span>
    <span class="br0">&#41;</span> \
    <span class="kw5">-Path</span> <span class="st0">'OU=Service Accounts,DC=contoso,DC=com'</span>
&nbsp;
<span class="co1"># 3. Reboot each node OR run gpupdate /force + klist purge -li 0x3e7</span>
<span class="co1">#    so the computer picks up its new group membership</span></pre></div></div>
<p>That last step is the one most people skip and then spend an hour debugging. Computer Kerberos tickets are issued at boot. Adding a computer to a new security group requires a reboot or a TGT refresh before the computer can retrieve the gMSA password.</p>
<p>Then on each SQL Server host:</p>
<div id="wpshdo_8" class="wp-synhighlighter-outer"><div id="wpshdt_8" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_8"></a><a id="wpshat_8" class="wp-synhighlighter-title" href="#codesyntax_8"  onClick="javascript:wpsh_toggleBlock(8)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_8" onClick="javascript:wpsh_code(8)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_8" onClick="javascript:wpsh_print(8)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_8" class="wp-synhighlighter-inner" style="display: block;"><pre class="powershell" style="font-family:monospace;"><span class="co1"># Install the AD PowerShell module if not present</span>
Install<span class="sy0">-</span>WindowsFeature RSAT<span class="sy0">-</span>AD<span class="sy0">-</span>PowerShell
&nbsp;
<span class="co1"># Install and verify the gMSA on this host</span>
Install<span class="sy0">-</span>ADServiceAccount <span class="sy0">-</span>Identity <span class="st0">'SQLEng_PRODAG01'</span>
Test<span class="sy0">-</span>ADServiceAccount <span class="sy0">-</span>Identity <span class="st0">'SQLEng_PRODAG01'</span>   <span class="co1"># must return True</span></pre></div></div>
<p><strong>Test-ADServiceAccount</strong> returning <strong>True</strong> is the gate. If it returns <strong>False</strong>, do not proceed to the SQL Server side — the problem is upstream in AD or group membership.</p>
<h3>Assigning the gMSA to SQL Server</h3>
<p>Use SQL Server Configuration Manager. Always. Not services.msc, not Server Manager, not the Services snap-in. SQL Server Configuration Manager grants the necessary local rights (<em>Log on as a service</em>, <em>Lock pages in memory</em>, file system ACLs, registry ACLs) automatically. The other tools don&#8217;t, and you&#8217;ll spend the rest of your afternoon figuring out why SQL Server won&#8217;t start.</p>
<p>In Configuration Manager: right-click the SQL Server service, Properties, Log On tab, enter <strong>CONTOSO\SQLEng_PRODAG01$</strong> in the account name field. Two things to remember:</p>
<ul>
<li>Always include the trailing $. This is how Windows distinguishes a managed service account from a regular user account.</li>
<li>Leave the password fields blank. If you type anything in them, the dialog will reject the save.</li>
</ul>
<p>Repeat for SQL Agent, SSRS, etc., each with its own gMSA. Then restart the services.</p>
<h3>Availability Groups and FCIs: The Extra Step</h3>
<p>For Always On Availability Groups, after switching the Database Engine service to a gMSA, you need to grant the new account CONNECT permission on the HADR endpoint on every replica. This is the step that breaks AGs silently — the cluster looks fine, but synchronization stops.</p>
<div id="wpshdo_9" class="wp-synhighlighter-outer"><div id="wpshdt_9" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_9"></a><a id="wpshat_9" class="wp-synhighlighter-title" href="#codesyntax_9"  onClick="javascript:wpsh_toggleBlock(9)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_9" onClick="javascript:wpsh_code(9)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_9" onClick="javascript:wpsh_print(9)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_9" class="wp-synhighlighter-inner" style="display: block;"><pre class="tsql" style="font-family:monospace;"><span class="kw1">USE</span> master;
&nbsp;
GO
&nbsp;
<span class="kw1">CREATE</span> LOG<span class="sy0">IN</span> <span class="br0">[</span>CONTOSO\svc_SQL_PRODAG01$<span class="br0">]</span> <span class="kw1">FROM</span> W<span class="sy0">IN</span>DOWS;
&nbsp;
<span class="kw1">GRANT</span> <span class="kw1">CONNECT</span> <span class="kw1">ON</span> ENDPO<span class="sy0">IN</span>T::Hadr_endpoint <span class="kw1">TO</span> <span class="br0">[</span>CONTOSO\svc_SQL_PRODAG01$<span class="br0">]</span>;
&nbsp;
GO</pre></div></div>
<p>Run that on every replica. If you forget one, the missed replica will fall out of sync the moment its old service account credential expires.</p>
<p>For FCIs, no equivalent step is needed — the gMSA is just the service account, and the cluster resource picks it up.</p>
<h3>Deploying at Scale with dbatools</h3>
<p>If you&#8217;re rolling gMSAs across an estate, do it with dbatools. The <strong>Update-DbaServiceAccount</strong> command handles the local rights assignment correctly — same as Configuration Manager, but scriptable across many servers in a single pipeline.</p>
<div id="wpshdo_10" class="wp-synhighlighter-outer"><div id="wpshdt_10" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_10"></a><a id="wpshat_10" class="wp-synhighlighter-title" href="#codesyntax_10"  onClick="javascript:wpsh_toggleBlock(10)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_10" onClick="javascript:wpsh_code(10)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_10" onClick="javascript:wpsh_print(10)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_10" class="wp-synhighlighter-inner" style="display: block;"><pre class="powershell" style="font-family:monospace;"><span class="co1"># Switch the Database Engine on a list of servers to a gMSA</span>
<span class="re0">$instances</span> <span class="sy0">=</span> <span class="st0">'SQLNODE01'</span><span class="sy0">,</span><span class="st0">'SQLNODE02'</span><span class="sy0">,</span><span class="st0">'SQLNODE03'</span>
&nbsp;
Get<span class="sy0">-</span>DbaService <span class="kw5">-ComputerName</span> <span class="re0">$instances</span> <span class="sy0">-</span><span class="kw2">Type</span> Engine <span class="sy0">|</span>
    Update<span class="sy0">-</span>DbaServiceAccount <span class="sy0">-</span>Username <span class="st0">'CONTOSO\SQLEngPRODAG01$'</span>
&nbsp;
<span class="co1"># Verify it took</span>
Get<span class="sy0">-</span>DbaService <span class="kw5">-ComputerName</span> <span class="re0">$instances</span> <span class="sy0">-</span><span class="kw2">Type</span> Engine <span class="sy0">|</span>
    <span class="kw1">Select-Object</span> ComputerName<span class="sy0">,</span> ServiceName<span class="sy0">,</span> StartName<span class="sy0">,</span> State</pre></div></div>
<p>Note the lack of a <strong>-Password</strong> parameter. dbatools detects the trailing $ and treats the account as a managed service account, skipping the password prompt entirely. This is the kind of small touch that makes dbatools the right tool for this job.</p>
<h3>Common Pitfalls and How to Diagnose Them</h3>
<h4>&#8220;Cannot generate SSPI context&#8221;</h4>
<p>This is the canonical Kerberos failure. After switching to a gMSA, clients can&#8217;t connect via Kerberos and either fall back to NTLM (slow, less secure) or fail outright. The cause is almost always SPN-related — either the SPNs didn&#8217;t transfer to the gMSA, or duplicates exist on the old account.</p>
<p>Diagnose:</p>
<div id="wpshdo_11" class="wp-synhighlighter-outer"><div id="wpshdt_11" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_11"></a><a id="wpshat_11" class="wp-synhighlighter-title" href="#codesyntax_11"  onClick="javascript:wpsh_toggleBlock(11)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_11" onClick="javascript:wpsh_code(11)" title="Show code only"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_11" onClick="javascript:wpsh_print(11)" title="Print code"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img decoding="async" border="0" style="border: 0 none" src="https://sqlsolutionsgroup.com/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_11" class="wp-synhighlighter-inner" style="display: block;"><pre class="powershell" style="font-family:monospace;"><span class="co1"># Check what authentication SQL is using</span>
<span class="kw2">SELECT</span> auth_scheme FROM sys.dm_exec_connections <span class="kw3">WHERE</span> session_id <span class="sy0">=</span> <span class="sy0">@@</span>SPID;
<span class="sy0">--</span> Should <span class="kw3">return</span> KERBEROS<span class="sy0">,</span> not NTLM
&nbsp;
<span class="co1"># Find any SPN registered for your SQL service</span>
setspn <span class="sy0">-</span>Q MSSQLSvc<span class="sy0">/</span>PRODAG01.contoso.com
setspn <span class="sy0">-</span>Q MSSQLSvc<span class="sy0">/</span>PRODAG01.contoso.com:<span class="nu0">1433</span>
&nbsp;
<span class="co1"># Find duplicates (these break Kerberos entirely)</span>
setspn <span class="sy0">-</span>X</pre></div></div>
<p><strong>Fix</strong>: remove SPNs from the old service account, ensure they&#8217;re on the gMSA. If you registered SPNs in the <strong>New-ADServiceAccount</strong> command, AD will refresh them automatically going forward — that&#8217;s the gMSA SPN management benefit. If you didn&#8217;t, register them manually now and let AD take it from there.</p>
<h4>Linked servers and cross-server delegation</h4>
<p>If your SQL Server uses linked servers configured for Windows authentication pass-through, you need Kerberos delegation set on the gMSA. In AD Users and Computers, the gMSA must be configured for constrained delegation to the target SQL Server&#8217;s MSSQLSvc SPN. This is the same requirement as for any service account — gMSAs don&#8217;t change it — but it&#8217;s worth checking before you migrate, because constrained delegation settings don&#8217;t migrate automatically when you change accounts.</p>
<h4>Service won&#8217;t start after the switch</h4>
<p>Almost always one of:</p>
<ul>
<li>The gMSA wasn&#8217;t installed on the host (skipped Install-ADServiceAccount)</li>
<li>The computer account isn&#8217;t in the security group (or wasn&#8217;t rebooted after being added), or</li>
<li>The account was assigned via the wrong tool and didn&#8217;t get <em>Log on as a service</em>.</li>
</ul>
<p>The error in the event log is usually generic; the diagnostic order is: confirm Test-ADServiceAccount returns True, confirm group membership, redo the assignment via Configuration Manager.</p>
<h3>When Not to Use a gMSA</h3>
<p>Two scenarios where we don&#8217;t recommend gMSAs:</p>
<ul>
<li><strong>Servers in domains where you don&#8217;t control the KDS root key</strong>. You&#8217;ll need a Domain Admin to create that one-time. If your AD team won&#8217;t, it&#8217;s a non-starter.</li>
<li><strong>Cross-forest scenarios</strong>. gMSAs do not work across AD forest boundaries. If your SQL Server needs to authenticate to resources in a different forest, you need a regular service account or a different design.</li>
</ul>
<h3>Bottom Line</h3>
<p>gMSAs are the right default for service accounts on any domain-joined SQL Server built in the last decade. The setup overhead is real but one-time. The ongoing operational savings — no password rotations, no expiry surprises, no &#8220;who has the spreadsheet of service account passwords&#8221; conversations — pay for it many times over.</p>
<p>If you&#8217;re standing up a new SQL Server in 2026 and you&#8217;re not using a gMSA, you should have a specific reason why. &#8220;We&#8217;ve always done it this way&#8221; isn&#8217;t one.</p>
<hr />
<h4><em><strong>Need help rolling gMSAs out across an existing estate? </strong></em></h4>
<p>SSG has done this dozens of times across customer environments — including the messy migrations from legacy service accounts on production AGs. <a href="https://sqlsolutionsgroup.com/contact-us/">Get in touch with us</a> and we&#8217;d be happy to support you.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/group-managed-service-accounts/">Group Managed Service Accounts and SQL Server: What You Actually Need to Know</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sqlsolutionsgroup.com/group-managed-service-accounts/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>SQL Server AG Won’t Become Primary After Force Quorum? Here’s Why and How to Fix It</title>
		<link>https://sqlsolutionsgroup.com/primary-after-force-quorum/</link>
					<comments>https://sqlsolutionsgroup.com/primary-after-force-quorum/#comments</comments>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Thu, 05 Jun 2025 12:34:32 +0000</pubDate>
				<category><![CDATA[SQL Server]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=7252</guid>

					<description><![CDATA[<p>If you’ve encountered a situation where none of your SQL Server Always On Availability Group (AG) replicas become PRIMARY after a cluster failure — you’re not alone.  We recently had a customer with this exact scenario (AG won’t become primary after force quorum), and it is both uncommon and difficult to troubleshoot so I thought it would be worth posting about.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/primary-after-force-quorum/">SQL Server AG Won’t Become Primary After Force Quorum? Here’s Why and How to Fix It</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Overview</h2>
<p>If you’ve encountered a situation where none of your SQL Server Always On Availability Group (AG) replicas become PRIMARY after a cluster failure — you’re not alone.  We recently had a customer with this exact scenario (AG won’t become primary after force quorum), and it is both uncommon and difficult to troubleshoot so I thought it would be worth posting about.</p>
<ul>
<li>What causes this issue</li>
<li>Why all replicas can get stuck in SECONDARY state</li>
<li>How to resolve the issue safely</li>
</ul>
<hr />
<h2>The Scenario</h2>
<p>You have a two-node Always On AG across two subnets. Due to a network failure or maintenance in which one of both subnets become unavailable:</p>
<ul>
<li>The Windows Server Failover Cluster (WSFC) loses quorum</li>
<li>The second node is unreachable or has been evicted</li>
<li>In Failover Cluster Manager, the AG Role is in a Failed state and will not come online.</li>
<li>In SQL Server Management Studio:
<ul>
<li>Both replicas show as <strong>SECONDARY</strong></li>
<li>SQL Server refuses to allow any failover with the following error:</li>
</ul>
</li>
</ul>
<blockquote><p><strong>&#8220;The availability replica on this instance cannot become the primary replica because the WSFC cluster was started in force quorum.&#8221;</strong></p></blockquote>
<hr />
<h2>What’s Actually Happening?</h2>
<p>This is SQL Server protecting you from a <strong>split-brain</strong> scenario. When you Force the Cluster Online due to quorum issues, SQL Server doesn&#8217;t trust that it&#8217;s safe to assign a PRIMARY replica.</p>
<p>So, it <strong>intentionally refuses to promote any replica</strong> to PRIMARY — even if the cluster seems healthy on the surface. This is referred to as split-brain, passive state mode. It is protecting itself since it doesn&#8217;t know which node the cluster is going to choose when / if it brings the AG role online. In this state, all the databases are in <em><strong>Not Synchronized, </strong></em>and you can&#8217;t even remove them from the AG since that has to be done on the PRIMARY replica.</p>
<h2>Resolution</h2>
<h3>Step 1: Fix the Cluster</h3>
<p>In the scenario we encountered, the root cause was a DNS issue with both the Cluster IP and the Listener IP on the secondary subnet, causing the IP Addresses to show up as Failed instead of Offline. Fixing the DNS issue and restarting the cluster resolved this.</p>
<p>This clears the “forced” quorum state and allows SQL Server to trust the cluster again.</p>
<h3>Step 2: Restart SQL Server</h3>
<p>This forces a recheck of the AG and WSFC state but will not fix the AG. Multiple reboots, cluster restarts, service restarts will not do that. Remember, it is protecting itself.</p>
<h3>Step 3: Force Failover Allow Data Loss</h3>
<p>This is a special command that should only be used in cases like this. Although allow data loss sounds scary, in this case it is quite safe since both replicas are secondaries, and no data has changed.</p>
<p>The command should be run on the secondary <strong>that you want to be primary</strong>, ideally the same server that was primary prior to the cluster failure.</p>
<pre><code>ALTER AVAILABILITY GROUP [YourAG] FORCE_FAILOVER_ALLOW_DATA_LOSS;</code></pre>
<p>This command promotes the current replica to PRIMARY even if it wasn’t fully synchronized. It basically tells SQL Server to skip the checks with the WSFC and to trust you that this should be the primary.</p>
<hr />
<h2>🔍 Post-Failover Cleanup</h2>
<p>After promotion, check the state of your AG:</p>
<pre><code>
SELECT 
  replica_server_name,
  role_desc,
  synchronization_state_desc,
  connected_state_desc
FROM sys.dm_hadr_availability_replica_states;
</code></pre>
<p>You will likely need to resume data movement on the databases to get the secondary back in sync and, in worst case scenarios, you may have to reseed the databases on the secondary</p>
<hr />
<h2>Microsoft Docs Reference</h2>
<p>For more details, see Microsoft’s official documentation: <a href="https://learn.microsoft.com/en-us/sql/database-engine/availability-groups/windows/perform-a-forced-manual-failover-of-an-availability-group-sql-server" target="_blank" rel="noopener">Perform a Forced Manual Failover of an Availability Group (Microsoft Docs)<br />
</a></p>
<hr />
<h2>Lessons Learned</h2>
<ul>
<li>SQL Server is cautious with failovers — and that’s a good thing</li>
<li>Forced quorum is a tool, not a fix — clear it as soon as possible</li>
<li>AGs won&#8217;t elect a PRIMARY without trust in WSFC&#8217;s integrity</li>
<li>Document and test your disaster recovery plan in lower environments</li>
</ul>
<hr />
<h2>Final Word</h2>
<p>The `FORCE_FAILOVER_ALLOW_DATA_LOSS` command can feel scary, but when used correctly — as in this scenario where both nodes thought they were SECONDARY — it’s the right call.</p>
<p>Knowing how to handle these edge cases will keep your high availability setup truly available — even in the worst-case scenarios.</p>
<p><!-- END OF WORDPRESS BLOG POST --></p>
<p>The post <a href="https://sqlsolutionsgroup.com/primary-after-force-quorum/">SQL Server AG Won’t Become Primary After Force Quorum? Here’s Why and How to Fix It</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sqlsolutionsgroup.com/primary-after-force-quorum/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Ticking Timebombs: Object Ownership and System Databases Gone Wrong</title>
		<link>https://sqlsolutionsgroup.com/sql-server-object-ownership/</link>
					<comments>https://sqlsolutionsgroup.com/sql-server-object-ownership/#comments</comments>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Tue, 18 May 2021 06:43:00 +0000</pubDate>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[#microsftcertifedmaster]]></category>
		<category><![CDATA[#microsftpartner]]></category>
		<category><![CDATA[#SQLAB]]></category>
		<category><![CDATA[#SQlatino]]></category>
		<category><![CDATA[#SQlatinoamerica]]></category>
		<category><![CDATA[#sqldatabase]]></category>
		<category><![CDATA[#sqldeveloper]]></category>
		<category><![CDATA[#SQLgroupie]]></category>
		<category><![CDATA[#sqlimer]]></category>
		<category><![CDATA[#sqlimerbymay]]></category>
		<category><![CDATA[#sqlinjection]]></category>
		<category><![CDATA[#sqlinternals]]></category>
		<category><![CDATA[#sqlite]]></category>
		<category><![CDATA[#sqlite3]]></category>
		<category><![CDATA[#SQLLearning]]></category>
		<category><![CDATA[#SQLMagazine]]></category>
		<category><![CDATA[#sqlmanagementstudio]]></category>
		<category><![CDATA[#sqlmanager]]></category>
		<category><![CDATA[#Sqlmap]]></category>
		<category><![CDATA[#sqlrun]]></category>
		<category><![CDATA[#sqlsaturday2017]]></category>
		<category><![CDATA[#sqlsatvienna]]></category>
		<category><![CDATA[#sqlserver]]></category>
		<category><![CDATA[#SQLserver2012]]></category>
		<category><![CDATA[#sqlserver2014]]></category>
		<category><![CDATA[#sqlserver2017]]></category>
		<category><![CDATA[#sqlserver2022]]></category>
		<category><![CDATA[#SQLServeronLinux]]></category>
		<category><![CDATA[#SQLsolutionsgroup]]></category>
		<category><![CDATA[#SQLTraining]]></category>
		<category><![CDATA[#SQLYog]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLPASS]]></category>
		<category><![CDATA[SQLSaturday]]></category>
		<category><![CDATA[SSG]]></category>
		<category><![CDATA[Trace Flag]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=6410</guid>

					<description><![CDATA[<p>Our Health Check is a great starting point with our clients. It tells us a lot about their instances, such as glaring problems we have to fix immediately. It also reveals issues that may not be a problem now, but they could blow up soon. We always point out these ticking timebombs to our customers [&#8230;]</p>
<p>The post <a href="https://sqlsolutionsgroup.com/sql-server-object-ownership/">Ticking Timebombs: Object Ownership and System Databases Gone Wrong</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Our <a href="https://sqlsolutionsgroup.com/services/sql-health-check/"><u>Health Check</u></a> is a great starting point with our clients. It tells us a lot about their instances, such as glaring problems we have to fix immediately. It also reveals issues that may not be a problem <em>now</em>, but they could blow up soon. We always point out these ticking timebombs to our customers because they have the potential to create problems down the road. These tend to be issues that are not affecting performance or security, etc.</p>



<p class="wp-block-paragraph">In this post, I&#8217;ll walk you through a real-world situation tied to SQL Server object ownership where a timebomb went off. The two best practices involved here are:</p>



<ul class="wp-block-list">
<li>Don’t put user objects in system databases.</li>
<li>Ensure the default built-in logins <strong>sa</strong> or <strong>dbo</strong>. own all objects, databases, jobs, etc.</li>
</ul>



<h3 class="wp-block-heading"><strong>Patching Time Bomb</strong></h3>



<p class="wp-block-paragraph">Recently while installing a SQL Server service pack on one of our customer’s servers (fortunately a non-production instance), the SQL Server service would not start after reboot. I checked the usual suspects (permissions, service account issues) and checked if the Windows Event Log could give me a clue. There was nothing except the generic error in the System log that the service could not start.</p>



<p class="wp-block-paragraph">So it was time to dig into the SQL Server Error Log. Even though the service would not start, the log is just a text file and does not need to be accessed through the server. The default location of the log is <strong>C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Log</strong>, replacing the version and instance folders as needed.</p>



<p class="wp-block-paragraph">Note that there is a file for each error log as they are cycled and retained. So the log from the most recent restart (or restart attempt, in this case) is named <strong>ERRORLOG</strong>, with the archived logs named <strong>ERRORLOG.#</strong> for each of the archived logs.</p>



<p class="wp-block-paragraph">Looking at the log in this particular case, I noted the following errors.</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="804" height="366" class="wp-image-6411" src="https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image.png" alt="SQL Server Object Ownership" srcset="https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image.png 804w, https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image-300x137.png 300w, https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image-768x350.png 768w" sizes="(max-width: 804px) 100vw, 804px" /></figure>



<p class="wp-block-paragraph">Anytime you see something that says &#8220;restore the master database from backup&#8221; it&#8217;s not a good thing. However, looking a bit further back we see that the initial error indicates there is already an object named <strong>DatabaseMailUserRole</strong> in the database. That is followed by a <strong>CREATE SCHEMA </strong>failure, all of which took place during the <strong>msdb</strong> upgrade script. So the next step is to dig into the msdb database and find out what’s going on.</p>



<p class="wp-block-paragraph">But if the service won’t start, how do I get into the database and figure out what’s going on with those objects?</p>



<h3 class="wp-block-heading"><strong>Enter Trace Flag 902</strong></h3>



<p class="wp-block-paragraph">We use Trace Flag 902 for this exact purpose. When an upgrade goes wrong, every time you start the service it will attempt to run the upgrade script. Doing so generates the same failure. This is because the instance is in “Script Upgrade Mode.” Trace Flag 902 tells SQL Server to startup and recover databases without running any pending upgrade scripts. That way you can get in, find and fix the problem, then restart the server again without the trace flag.</p>



<p class="wp-block-paragraph">The easiest way to start the service with a temporary trace flag is from the command line.</p>



<figure class="wp-block-image"><img decoding="async" width="415" height="43" class="wp-image-6412" src="https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image-1.png" alt="" srcset="https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image-1.png 415w, https://sqlsolutionsgroup.com/wp-content/uploads/2021/05/word-image-1-300x31.png 300w" sizes="(max-width: 415px) 100vw, 415px" /></figure>



<p class="wp-block-paragraph">After executing that command, the service started and all of the databases came up normally.</p>



<p class="wp-block-paragraph">Looking into the actual issue, I found that the script deleted <strong>DatabaseMailUserRole</strong> as it was not there. Digging a little deeper, it turns out there was a second database role owned by that role, which in turned owned the schema in question. So when the upgrade script tried to upgrade that schema, it failed because it was effectively orphaned. Modifying the ownership of the schema to <strong>dbo</strong> (as it should be) and restarting the instance without the trace flag fixed the problem and the upgrade completed. I ran the Service Pack installer a second time to be sure it got everything. Sure enough it said “Incomplete” for the database engine. This time the install completed and rebooted with no issues.</p>



<h3 class="wp-block-heading"><strong>Conclusions</strong></h3>



<p class="wp-block-paragraph">So we see an issue with two Best Practices here:</p>



<ol class="wp-block-list">
<li>Creation of user objects (in this case a role) in the msdb database.</li>
<li>Changing the SQL Server object ownership of a schema to use that role.</li>
</ol>



<p class="wp-block-paragraph">I don’t know how long it had been this way nor how it got that way. But it’s a great example of something that is just sitting there, seemingly benign, until the ticking stops and the bomb goes off.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/sql-server-object-ownership/">Ticking Timebombs: Object Ownership and System Databases Gone Wrong</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sqlsolutionsgroup.com/sql-server-object-ownership/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>T-SQL Anti-Patterns: SQL User Defined Functions (UDFs) that turn your set operation into a cursor</title>
		<link>https://sqlsolutionsgroup.com/t-sql-anti-patterns-user-defined-functions/</link>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Wed, 03 Mar 2021 01:58:09 +0000</pubDate>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[#microsftcertifedmaster]]></category>
		<category><![CDATA[#microsftpartner]]></category>
		<category><![CDATA[#SQLAB]]></category>
		<category><![CDATA[#SQlatino]]></category>
		<category><![CDATA[#SQlatinoamerica]]></category>
		<category><![CDATA[#sqldatabase]]></category>
		<category><![CDATA[#sqldeveloper]]></category>
		<category><![CDATA[#SQLgroupie]]></category>
		<category><![CDATA[#sqlimer]]></category>
		<category><![CDATA[#sqlimerbymay]]></category>
		<category><![CDATA[#sqlinjection]]></category>
		<category><![CDATA[#sqlinternals]]></category>
		<category><![CDATA[#sqlite]]></category>
		<category><![CDATA[#sqlite3]]></category>
		<category><![CDATA[#SQLLearning]]></category>
		<category><![CDATA[#SQLMagazine]]></category>
		<category><![CDATA[#sqlmanagementstudio]]></category>
		<category><![CDATA[#sqlmanager]]></category>
		<category><![CDATA[#Sqlmap]]></category>
		<category><![CDATA[#sqlrun]]></category>
		<category><![CDATA[#sqlsaturday2017]]></category>
		<category><![CDATA[#sqlsatvienna]]></category>
		<category><![CDATA[#sqlserver]]></category>
		<category><![CDATA[#SQLserver2012]]></category>
		<category><![CDATA[#sqlserver2014]]></category>
		<category><![CDATA[#sqlserver2017]]></category>
		<category><![CDATA[#sqlserver2022]]></category>
		<category><![CDATA[#SQLServeronLinux]]></category>
		<category><![CDATA[#SQLsolutionsgroup]]></category>
		<category><![CDATA[#SQLTraining]]></category>
		<category><![CDATA[#SQLYog]]></category>
		<category><![CDATA[set operations]]></category>
		<category><![CDATA[SQLPASS]]></category>
		<category><![CDATA[SQLSaturday]]></category>
		<category><![CDATA[SSG]]></category>
		<category><![CDATA[T-SQL]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=6208</guid>

					<description><![CDATA[<p>One of the things we see as consultants are consistent patterns of behavior by T-SQL developers that cause big performance problems. I call these anti-patterns. Today I want to specifically address SQL User Defined Functions (UDFs). SQL Server 2000 introduced UDFs. While they can be useful in certain situations, an all too prevalent anti-pattern has [&#8230;]</p>
<p>The post <a href="https://sqlsolutionsgroup.com/t-sql-anti-patterns-user-defined-functions/">T-SQL Anti-Patterns: SQL User Defined Functions (UDFs) that turn your set operation into a cursor</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">One of the things we see as consultants are consistent patterns of behavior by T-SQL developers that cause big performance problems. I call these anti-patterns. Today I want to specifically address SQL User Defined Functions (UDFs).</p>



<p class="wp-block-paragraph">SQL Server 2000 introduced UDFs. While they can be useful in certain situations, an all too prevalent anti-pattern has emerged.</p>



<h3 class="wp-block-heading">SQL User Defined Functions: Identifying The Problem</h3>



<p class="wp-block-paragraph">To illustrate this, let&#8217;s take a simple example from the <strong>AdventureWorks</strong>  sample database. If you don’t have this database, you can <a title="AdventureWorks" href="https://msftdbprodsamples.codeplex.com/" target="_blank" rel="noopener noreferrer">download</a> and install it. This is a good thing to have on your personal development or lab SQL Server instance, as many blogs, books, and articles use it for examples.</p>



<p class="wp-block-paragraph">In our example, we are going to generate a simple report for the <strong>AdventureWorks</strong> Human Resources department using the following tables.</p>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb.png" alt="SQL user defined functions" /></a></figure>



<p class="wp-block-paragraph">Our report will consist of the employee’s name, the department they work in, their job title, and start date. We have a mock-up of the report that the end user would like to see:</p>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image1.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb1.png" alt="image" /></a></figure>



<p class="wp-block-paragraph">Taking a look at the schema above, we realize that the <strong>EmployeeDepartmentHistory</strong> table has most of this information. So we start there.</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">SELECT BusinessEntityID AS EmployeeID,
       DepartmentID,
       StartDate
FROM HumanResources.EmployeeDepartmentHistory</code></pre>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image2.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb2.png" alt="image" /></a></figure>



<p class="wp-block-paragraph">This gets us the <strong>EmployeeID </strong>and <strong>DepartmentID</strong>, but not the actual names. As developers, we are big into encapsulating code as much as possible to avoid repetitive code and the manageability issues that come with it. We know that UDFs in SQL Server can help with this so we create the following function to get the department name:</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">CREATE FUNCTION dbo.GetDepartment
(
    @DepartmentID INT
)
RETURNS VARCHAR(40)
AS
BEGIN
    DECLARE @ret VARCHAR(40)
    SET @ret =
    (
        SELECT [Name]
        FROM HumanResources.Department
        WHERE DepartmentID = @DepartmentID
    )
    RETURN @ret
END</code></pre>



<p class="wp-block-paragraph">Now we can execute the same query but call the new function to return the department name.</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">SELECT
     BusinessEntityID AS EmployeeID,
     dbo. GetDepartment(DepartmentID) AS DepartmentName,
     StartDate
 FROM HumanResources. EmployeeDepartmentHistory</code></pre>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image3.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb3.png" alt="SQL user defined functions" /></a></figure>



<p class="wp-block-paragraph">That worked great so we do the same thing for <strong>EmployeeName</strong> and <strong>JobTitle</strong>.</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">CREATE FUNCTION dbo. GetEmployeeName(@EmployeeID int)
RETURNS VARCHAR(40)
AS
BEGIN
  DECLARE @ret VARCHAR(40), @ContactID INT 

  --get contactid
  SELECT @ContactID = BusinessEntityID FROM HumanResources. Employee WHERE BusinessEntityID = @EmployeeID

  --get name
  SET @ret = (	SELECT coalesce(FirstName,'') + ' ' + coalesce(MiddleName,'') + ' ' + coalesce(LastName,'')
				FROM Person. Person
				WHERE BusinessEntityID = @ContactID
			  )

  RETURN @ret
END</code></pre>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">CREATE FUNCTION dbo.GetJobTitle
(
    @EmployeeID INT
)
RETURNS VARCHAR(40)
AS
BEGIN
    DECLARE @ret VARCHAR(40)
    SET @ret =
    (
        SELECT [JobTitle]
        FROM HumanResources.Employee
        WHERE BusinessEntityID = @EmployeeID
    )
    RETURN @ret
END</code></pre>



<p class="wp-block-paragraph">Executing the query again using the three functions we&#8217;ve created, we get the data we are looking for. We have encapsulated the code into function for re-use in other places, and we avoided those pesky joins. The resulting query is clean and simple. Best of all, this is <strong>a single query</strong> so we’re doing a set operation like our DBA has told us we should do.</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">SELECT
	dbo. GetEmployeeName(BusinessEntityID) as EmployeeName,
	dbo. GetDepartment(DepartmentID) AS DepartmentName,
	dbo. GetJobTitle(BusinessEntityID),
	StartDate
FROM HumanResources. EmployeeDepartmentHistory</code></pre>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image4.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb4.png" alt="SQL user defined functions" /></a></figure>



<h3 class="wp-block-heading"><strong><em>So what’s the problem?</em></strong></h3>



<p class="wp-block-paragraph">The problem is that we have unwittingly turned our single query into a loop by introducing these functions. Because the functions are non-deterministic, they have to be called for each row in our result set.</p>



<p class="wp-block-paragraph">To see this, let’s fire up our old friend SQL Server Profiler, which shows us the actual executing statements and the accompanying resources used. We’ll use the following trace definition to keep things as simple and clean as possible:</p>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image5.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb5.png" alt="image" /></a></figure>



<p class="wp-block-paragraph">Let’s execute our query and see what we get.</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">SELECT
	dbo. GetEmployeeName(BusinessEntityID) as EmployeeName,
	dbo. GetDepartment(DepartmentID) AS DepartmentName,
	dbo. GetJobTitle(BusinessEntityID),
	StartDate
FROM HumanResources. EmployeeDepartmentHistory</code></pre>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image6.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb6.png" alt="image" /></a></figure>



<p class="wp-block-paragraph">Wait a minute. Our single-statement query just generated 2076 individual SQL Statements, generating a total of 2,672 logical reads. If we look through the profiler results carefully, we can see that each of the three functions was called once for each of the 296 rows our query returned. So what looks like a simple set operation <strong>is, in fact, a loop</strong>.</p>



<p class="wp-block-paragraph">We go to our DBA for help and she explains that we need to get rid of the functions and use joins instead to make it into a true set operation. So we refactor the query as follows:</p>



<pre class="wp-block-code"><code class="language-sql line-numbers" lang="sql">SELECT
	COALESCE(c. FirstName,'') + ' ' + coalesce(c. MiddleName,'') + ' ' + coalesce(c. LastName,'') AS EmployeeName,
	d. name AS DepartmentName,
	e. JobTitle,
	StartDate
FROM HumanResources. EmployeeDepartmentHistory eh
	INNER JOIN HumanResources. Department d ON eh. DepartmentID = d. DepartmentID
	INNER JOIN HumanResources. Employee e ON e. BusinessEntityID = eh. BusinessEntityID
	INNER JOIN Person. Person c ON c. BusinessEntityID = e. BusinessEntityID</code></pre>



<figure class="wp-block-image"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image7.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb7.png" alt="image" /></a></figure>



<p class="wp-block-paragraph">Now if we execute the query and look at the profiler trace, we get just a single statement for a total of 1032 logical reads. Our query has become much more complicated and we don’t have the benefit of code encapsulation, but we&#8217;ve got the logical reads to less than half. And that was for only 296 rows.</p>



<figure class="wp-block-image is-resized"><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image8.png"><img decoding="async" title="image" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/10/image_thumb8.png" alt="SQL user defined functions" width="628" height="52" /></a></figure>



<h3 class="wp-block-heading">Conclusion</h3>



<p class="wp-block-paragraph">This is a simple example, but hopefully you can see the impact in a busy system with lots more data. I have seen this in production environments where something like <strong>GetCustomerName()</strong> is being called tens of millions of times <strong><em>daily</em></strong>.  This is a great example of an anti-pattern, where SQL user defined functions look like a great idea but the performance impact can be devastating.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/t-sql-anti-patterns-user-defined-functions/">T-SQL Anti-Patterns: SQL User Defined Functions (UDFs) that turn your set operation into a cursor</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Skill Up or Give Up: Azure Data Studio or Bust</title>
		<link>https://sqlsolutionsgroup.com/skill-up-or-give-up-azure-data-studio-or-bust/</link>
					<comments>https://sqlsolutionsgroup.com/skill-up-or-give-up-azure-data-studio-or-bust/#comments</comments>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Mon, 22 Feb 2021 11:25:00 +0000</pubDate>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[#microsftcertifedmaster]]></category>
		<category><![CDATA[#microsftpartner]]></category>
		<category><![CDATA[#SQLAB]]></category>
		<category><![CDATA[#SQlatino]]></category>
		<category><![CDATA[#SQlatinoamerica]]></category>
		<category><![CDATA[#sqldatabase]]></category>
		<category><![CDATA[#sqldeveloper]]></category>
		<category><![CDATA[#SQLgroupie]]></category>
		<category><![CDATA[#sqlimer]]></category>
		<category><![CDATA[#sqlimerbymay]]></category>
		<category><![CDATA[#sqlinjection]]></category>
		<category><![CDATA[#sqlinternals]]></category>
		<category><![CDATA[#sqlite]]></category>
		<category><![CDATA[#sqlite3]]></category>
		<category><![CDATA[#SQLLearning]]></category>
		<category><![CDATA[#SQLMagazine]]></category>
		<category><![CDATA[#sqlmanagementstudio]]></category>
		<category><![CDATA[#sqlmanager]]></category>
		<category><![CDATA[#Sqlmap]]></category>
		<category><![CDATA[#sqlrun]]></category>
		<category><![CDATA[#sqlsaturday2017]]></category>
		<category><![CDATA[#sqlsatvienna]]></category>
		<category><![CDATA[#sqlserver]]></category>
		<category><![CDATA[#SQLserver2012]]></category>
		<category><![CDATA[#sqlserver2014]]></category>
		<category><![CDATA[#sqlserver2017]]></category>
		<category><![CDATA[#sqlserver2022]]></category>
		<category><![CDATA[#SQLServeronLinux]]></category>
		<category><![CDATA[#SQLsolutionsgroup]]></category>
		<category><![CDATA[#SQLTraining]]></category>
		<category><![CDATA[#SQLYog]]></category>
		<category><![CDATA[ads]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLPASS]]></category>
		<category><![CDATA[SQLSaturday]]></category>
		<category><![CDATA[SSG]]></category>
		<category><![CDATA[ssms]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=6207</guid>

					<description><![CDATA[<p>One of the things I have found over the years is that it is easy to get into a rut and do things &#8220;the way I&#8217;ve always done them.&#8221; While this is perfectly natural, it also leads to a degradation of skills over time. Even more importantly, there may be a MUCH easier way to [&#8230;]</p>
<p>The post <a href="https://sqlsolutionsgroup.com/skill-up-or-give-up-azure-data-studio-or-bust/">Skill Up or Give Up: Azure Data Studio or Bust</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">One of the things I have found over the years is that it is easy to get into a rut and do things &#8220;the way I&#8217;ve always done them.&#8221; While this is perfectly natural, it also leads to a degradation of skills over time. Even more importantly, there may be a MUCH easier way to do something with newer tools or techniques.</p>



<p class="wp-block-paragraph">A great example of this is going back to when SQL 2005 was released. This was a massive change to SQL Server with the introduction of SQL Server Management Studio (SSMS), Dynamic Management Objects (i.e. DMVs and DMFs) and much more. For those of us who had been using the product for quite some time, getting rid of Enterprise Manager and Query Analyzer was big deal and a steep learning curve.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="700" height="328" class="wp-image-6248" src="https://sqlsolutionsgroup.com/wp-content/uploads/2021/02/Skills.jpg" alt="" srcset="https://sqlsolutionsgroup.com/wp-content/uploads/2021/02/Skills.jpg 700w, https://sqlsolutionsgroup.com/wp-content/uploads/2021/02/Skills-300x141.jpg 300w" sizes="(max-width: 700px) 100vw, 700px" /></figure>



<p class="wp-block-paragraph">DMVs were even worse. To this day I still find myself querying old system tables such as <strong>sysfiles </strong>or <strong>sysprocesses </strong>when I&#8217;m not thinking about it. In fact, in the spirit of full disclosure, I did not really focus on using DMVs and upgrading those skills until 2008 or so when I attended a pre-conference workshop on DMVs given by <a href="https://twitter.com/kekline" target="_blank" rel="noreferrer noopener">Kevin Kline</a> (Twitter).</p>



<p class="wp-block-paragraph">What does this have to do with being a DBA in 2021? <em><strong>Everything</strong></em>. We have seen massive changes to the Microsoft Data Platform over the last 5-10 years — PowerShell, Azure, other cloud platforms, and the advent of technologies such as NoSQL databases and Big Data to name a few.</p>



<p class="wp-block-paragraph">In 2018, Microsoft released <a href="https://docs.microsoft.com/en-us/sql/azure-data-studio/what-is-azure-data-studio?view=sql-server-ver15" target="_blank" rel="noreferrer noopener">Azure Data Studio (ADS)</a>. ADS is a fork of Visual Studio Code, so if you&#8217;ve used that at all it will be very familiar. Like many others, I have not been super fast to adopt and start using it.</p>



<p class="wp-block-paragraph">In the spirit of skilling up, my co-worker <a href="https://twitter.com/SQLScott" target="_blank" rel="noreferrer noopener">Scott Klein</a> and I were discussing this a couple of weeks ago and we hatched a plan: For the next 30 days, we are both going to force ourselves to use ADS for everything we do.</p>



<p class="wp-block-paragraph">Then, on <strong>March 17th</strong>, Scott will host a <a href="https://www.eventbrite.com/e/throw-down-ssms-vs-ads-tickets-141920057713" target="_blank" rel="noreferrer noopener">Webinar</a> on SSMS vs. ADS and what our experience has been. Watch for a blog from Scott in the next day or two for background on this battle of the apps.</p>



<p class="has-text-align-center has-medium-font-size wp-block-paragraph"><strong>Fasten your seat belts! This is going to be a blast. </strong></p>



<p class="wp-block-paragraph">&nbsp;</p>
<p>The post <a href="https://sqlsolutionsgroup.com/skill-up-or-give-up-azure-data-studio-or-bust/">Skill Up or Give Up: Azure Data Studio or Bust</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sqlsolutionsgroup.com/skill-up-or-give-up-azure-data-studio-or-bust/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Five Tips: Configure Windows for Better SQL Server Performance</title>
		<link>https://sqlsolutionsgroup.com/configure-windows-better-sql-server/</link>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Mon, 16 Nov 2020 12:29:36 +0000</pubDate>
				<category><![CDATA[SQL Group]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[#microsftcertifedmaster]]></category>
		<category><![CDATA[#microsftpartner]]></category>
		<category><![CDATA[#SQLAB]]></category>
		<category><![CDATA[#SQlatino]]></category>
		<category><![CDATA[#SQlatinoamerica]]></category>
		<category><![CDATA[#sqldatabase]]></category>
		<category><![CDATA[#sqldeveloper]]></category>
		<category><![CDATA[#SQLgroupie]]></category>
		<category><![CDATA[#sqlimer]]></category>
		<category><![CDATA[#sqlimerbymay]]></category>
		<category><![CDATA[#sqlinjection]]></category>
		<category><![CDATA[#sqlinternals]]></category>
		<category><![CDATA[#sqlite]]></category>
		<category><![CDATA[#sqlite3]]></category>
		<category><![CDATA[#SQLLearning]]></category>
		<category><![CDATA[#SQLMagazine]]></category>
		<category><![CDATA[#sqlmanagementstudio]]></category>
		<category><![CDATA[#sqlmanager]]></category>
		<category><![CDATA[#Sqlmap]]></category>
		<category><![CDATA[#sqlrun]]></category>
		<category><![CDATA[#sqlsaturday2017]]></category>
		<category><![CDATA[#sqlsatvienna]]></category>
		<category><![CDATA[#sqlserver]]></category>
		<category><![CDATA[#SQLserver2012]]></category>
		<category><![CDATA[#sqlserver2014]]></category>
		<category><![CDATA[#sqlserver2017]]></category>
		<category><![CDATA[#sqlserver2022]]></category>
		<category><![CDATA[#SQLServeronLinux]]></category>
		<category><![CDATA[#SQLsolutionsgroup]]></category>
		<category><![CDATA[#SQLTraining]]></category>
		<category><![CDATA[#SQLYog]]></category>
		<category><![CDATA[configurations]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLPASS]]></category>
		<category><![CDATA[SQLSaturday]]></category>
		<category><![CDATA[SSG]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[windows]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=5279</guid>

					<description><![CDATA[<p>I founded SQL Solutions Group 10 years ago (October 2010). In that time, we&#8217;ve done more than 100 Health Checks on customer systems. Based on that experience, we&#8217;re starting a series of posts to help you avoid pitfalls we often encounter. With this post, we show you how to configure Windows for better SQL Server [&#8230;]</p>
<p>The post <a href="https://sqlsolutionsgroup.com/configure-windows-better-sql-server/">Five Tips: Configure Windows for Better SQL Server Performance</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[I founded SQL Solutions Group 10 years ago (October 2010). In that time, we&#8217;ve done more than 100 <span style="text-decoration: underline;"><a href="https://sqlsolutionsgroup.com/services/sql-health-check/">Health Checks</a></span> on customer systems. Based on that experience, we&#8217;re starting a series of posts to help you avoid pitfalls we often encounter. With this post, we show you how to configure Windows for better SQL Server performance.

Not surprisingly, we see many of the same issues in almost every environment. This is an opportunity for us to share our knowledge in a series of blog posts. What we&#8217;ve learned from top offenders should be interesting and useful for our audience.

This post focuses on the Windows operating system and key configuration items that often get missed, which impairs performance.
<h3></h3>
<h3>Power Plan</h3>
The default Windows Power Plan in most environments is Balanced. which sounds good for power savings. But it does not work well for production SQL Server and can result in multiple types of CPU-related performance issues.

<span style="color: #f25e00;"><strong>Set the Power Plan to High</strong></span> on all SQL Server environments. Don’t forget to include the BIOS/UEFI and virtualization layer host operating system if applicable.

<a href="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks1.png"><img loading="lazy" decoding="async" class="aligncenter wp-image-5280 size-full" src="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks1.png" alt="Power plan settings are one way to configure Windows for better SQL Server" width="1015" height="440" /></a>

&nbsp;

Also note that many times this is a setting controlled by Active Directory Group Policy and you may need to override it for your SQL Servers. This is one of the many reasons we recommend you put your SQL Servers in their own organizational unit.
<h3></h3>
<h3>Disk Layout</h3>
Years ago, it was standard practice for the DBA to be involved in storage design and configuration. We gave a lot of thought into where to store the data files (in multiple filegroups), log files and backups. Splitting this across multiple volumes meant different physical disks/spindles. So we all did things like spreading data files across as many spindles as possible, separating indexes from data, and putting log files on storage optimized for sequential writes.

However, over the years storage area networks (SANs) have become more sophisticated, with volumes spread across disk pools containing hundreds of disks, tiering, virtualized storage, and so forth. Many in the industry think it no longer matters how we layout the data files. After all, the I/O is spread across all those disks anyway, right? Yes, that&#8217;s true at the <em>physical</em> storage level (the SAN). <em>But, </em>there is an entire storage path that the I/O travels to get there. Starting with the disk controller(s) at the OS level. Windows multi-threads and caches I/O at the controller level, so <strong><span style="color: #f25e00;">multiple drives on multiple controllers</span></strong> is still important for optimal performance.

<a href="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks2.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5281" src="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks2.png" alt="" width="3018" height="1427" /></a>
<h3></h3>
<h3>NTFS Block Size</h3>
In addition to spreading the I/O across multiple disks/controllers, take care how you format the volumes. The default allocation unit size for Windows volumes is 4K. Because of the way SQL Server I/O works, a larger block size is best. <strong><span style="color: #f25e00;">We recommend 64K</span></strong> as a starting point best practice, but in some cases even larger is better.

There are many ways to check this, but the easiest is using the <strong>fsutil</strong> command from an administrative command prompt.

<a href="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks3.png"><img loading="lazy" decoding="async" class="aligncenter wp-image-5282 size-full" src="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks3.png" alt="NFTS block size is another way to configure Windows for better SQL Server" width="996" height="510" /></a>
<h3></h3>
<h3>SQL Server Service Accounts</h3>
For a variety of reasons, such as providing least privileged access to domain resources as well as managing security on the local system, it is best to use a domain-based service account rather than the default built-in accounts for SQL Server. <span style="color: #f25e00;"><strong>We recommend a different account for each type of service (SQL Server, SQL Agent, SSRS, etc.) as well as per server</strong></span>. Use a naming convention to make these easy to identify. You can manage security across all SQL Servers by adding all service accounts to a global group. This allows one-at-a-time password changes, easier identification in audit logs as to which server has done something, etc.

<a href="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks4.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5283" src="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks4.png" alt="" width="1140" height="91" /></a>

In recent years, <span style="text-decoration: underline;"><a href="https://docs.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview">Group Managed Service Accounts (gMSA)</a></span> have become available and that is an even better solution. There are some caveats for using these with SQL Server, so be sure to review the details before using.
<h3></h3>
<h3>Windows User Rights</h3>
There are two Windows <span style="color: #f25e00;"><strong>User Rights that you should assign to the SQL Server Service Account</strong></span>. You can manage this via Group Policy or using the Local Security Policy management console on the server.
<ul>
 	<li><strong><em>Lock Pages in Memory (LPIM)</em></strong> &#8211; This allows SQLOS to better manage memory and avoid paging to disk.</li>
 	<li><strong><em>Perform Volume Maintenance Tasks (PVMT) </em></strong>&#8211; This enables Instant File Initialization (IFI) so that you don’t block data file creation and growth operations while the new space is zeroed.</li>
</ul>
<a href="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks5.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5284" src="https://sqlsolutionsgroup.com/wp-content/uploads/2020/11/HealthChecks5.png" alt="" width="1151" height="483" /></a>
<h3></h3>
<h3>Summary</h3>
These tips should help you configure Windows for better SQL Server outcomes and performance. True, the Windows OS Configuration might not seem that important when looking at the overall health of a SQL Server. But it (along with physical hardware and virtualization, when applicable) forms the foundation for SQL Server to run on. It&#8217;s important!

Getting it right will ensure that SQL Server is stable, secure, and high performance.

Our next post will get into instance-level SQL Server configuration tips.

<!-- /wp:post-content --><p>The post <a href="https://sqlsolutionsgroup.com/configure-windows-better-sql-server/">Five Tips: Configure Windows for Better SQL Server Performance</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What happened to SQL Server Data Tools in SQL Server 2014?</title>
		<link>https://sqlsolutionsgroup.com/sql-server-data-tools/</link>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Sat, 09 May 2020 17:00:00 +0000</pubDate>
				<category><![CDATA[SQL Group]]></category>
		<category><![CDATA[#microsftcertifedmaster]]></category>
		<category><![CDATA[#microsftpartner]]></category>
		<category><![CDATA[#SQLAB]]></category>
		<category><![CDATA[#SQlatino]]></category>
		<category><![CDATA[#SQlatinoamerica]]></category>
		<category><![CDATA[#sqldatabase]]></category>
		<category><![CDATA[#sqldeveloper]]></category>
		<category><![CDATA[#SQLgroupie]]></category>
		<category><![CDATA[#sqlimer]]></category>
		<category><![CDATA[#sqlimerbymay]]></category>
		<category><![CDATA[#sqlinjection]]></category>
		<category><![CDATA[#sqlinternals]]></category>
		<category><![CDATA[#sqlite]]></category>
		<category><![CDATA[#sqlite3]]></category>
		<category><![CDATA[#SQLLearning]]></category>
		<category><![CDATA[#SQLMagazine]]></category>
		<category><![CDATA[#sqlmanagementstudio]]></category>
		<category><![CDATA[#sqlmanager]]></category>
		<category><![CDATA[#Sqlmap]]></category>
		<category><![CDATA[#sqlrun]]></category>
		<category><![CDATA[#sqlsaturday2017]]></category>
		<category><![CDATA[#sqlsatvienna]]></category>
		<category><![CDATA[#sqlserver]]></category>
		<category><![CDATA[#SQLserver2012]]></category>
		<category><![CDATA[#sqlserver2014]]></category>
		<category><![CDATA[#sqlserver2017]]></category>
		<category><![CDATA[#sqlserver2022]]></category>
		<category><![CDATA[#SQLServeronLinux]]></category>
		<category><![CDATA[#SQLsolutionsgroup]]></category>
		<category><![CDATA[#SQLTraining]]></category>
		<category><![CDATA[#SQLYog]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQLPASS]]></category>
		<category><![CDATA[SQLSaturday]]></category>
		<category><![CDATA[SSDT]]></category>
		<category><![CDATA[SSG]]></category>
		<guid isPermaLink="false">http://sqlsolutionsgroup.com/?p=1479</guid>

					<description><![CDATA[<p>I&#8217;ve seen this question a few times and it is something that can be very confusing: You&#8217;ve installed SQL 2014 (a full version, not Express) and selected all components, yet when you go to your SQL Server 2014 program group, you can’t find SQL Server Data Tools. In all versions of SQL Server between 2005 [&#8230;]</p>
<p>The post <a href="https://sqlsolutionsgroup.com/sql-server-data-tools/">What happened to SQL Server Data Tools in SQL Server 2014?</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2014/06/server-2014-shadow.png"><img loading="lazy" decoding="async" class="alignright wp-image-1115" src="https://sqlsolutionsgroup.com/wp-content/uploads/2014/06/server-2014-shadow.png" alt="SQL Server Data Tools in SQL Server 2014" width="305" height="113" srcset="https://sqlsolutionsgroup.com/wp-content/uploads/2014/06/server-2014-shadow.png 659w, https://sqlsolutionsgroup.com/wp-content/uploads/2014/06/server-2014-shadow-300x111.png 300w" sizes="(max-width: 305px) 100vw, 305px" /></a>I&#8217;ve seen this question a few times and it is something that can be very confusing: You&#8217;ve installed SQL 2014 (a full version, not Express) and selected all components, yet when you go to your SQL Server 2014 program group, you can’t find SQL Server Data Tools.</p>
<p>In all versions of SQL Server between 2005 and 2012, the IDE for Business Intelligence projects has been included as part of the SQL Server installation. Based on Visual Studio, it gives you the ability to create BI projects in the Visual Studio Environment. In SQL Server versions 2005 through 2008 R2, it was called Business Intelligence Development Studio (BIDS). In SQL Server 2012 it was renamed to SQL Server Data Tools (SSDT) but was basically the same thing.</p>
<p>For some inexplicable reason, in SQL Server 2014 Microsoft decided not to include SSDT as part of the normal SQL Server installation. It is now a separate download. What is even more confusing is that there are different downloads depending on what you already have. If you go to the <a href="https://msdn.microsoft.com/en-us/hh297027.aspx">SQL Server Data Tools</a> download page on MSDN, there are several options for you to choose from.</p>
<hr />
<p class="has-text-align-center" style="font-size: 20px;">Need to upgrade the SQL Server skills of your team?</p>
<p class="has-text-align-center" style="font-size: 20px;">Leverage our expertise to create your own internal experts.</p>
<p class="has-text-align-center" style="font-size: 20px;"><span style="text-decoration: underline;">Learn More</span></p>
<hr />
<h3>If you have Visual Studio 2013</h3>
<blockquote><p><strong>SQL Server tooling in Visual Studio 2013</strong> &#8211; all the great database tools, now acquisition and updates are fully integrated in Express for Web, Express for Windows Desktop, Professional, Premium, and Ultimate. Since SQL Server tooling is included in VS, the updates will be pushed through VS Update and users will be prompted when VS is open. If you&#8217;d like to check for updates manually, open Visual Studio 2013 and choose the Tools &gt; Extensions and Updates menu. SQL Server tooling updates will appear in the Updates list.</p>
<p><a href="https://www.visualstudio.com/downloads/download-visual-studio-vs"><span style="color: #0000ff;">Download Visual Studio 2013 with SQL Server Tooling</span></a></p></blockquote>
<p>What is confusing is that from the download page the link sends you to, there is no mention of SSDT. You can download the various versions of Visual Studio Express or a 90-day trial of the full version of Visual Studio, but this still doesn&#8217;t get you SSDT. You have to add SQL Server tooling via VS Update. So if you don’t already have Visual Studio 2013, keep reading.</p>
<h3>If you have Visual Studio 2012</h3>
<blockquote><p><strong>SSDT Visual Studio 2012</strong> &#8211; provides a stand alone install experience as well as full integration into the Visual Studio Professional, Premium, and Ultimate SKUs. We are publishing the release through this page and the update feed.</p>
<p><a href="https://msdn.microsoft.com/en-us/jj650015"><span style="color: #0000ff;">Download SSDT for Visual Studio 2012</span></a></p></blockquote>
<p>This link leads you to a download which allows you to add SSDT to Visual Studio 2012.</p>
<h3>If you don’t have Visual Studio at all or have an older version</h3>
<blockquote><p><strong>SSDT-BI, SQL Server Business Intelligence</strong> is a distinct toolset from SSDT or the SQL Server database tooling in Visual Studio 2013. As part of the SQL Server 2014 release, SSDT-BI has released a version for Visual Studio 2013. For details, visit the <a href="https://blogs.msdn.com/b/analysisservices/archive/2014/04/02/sql-server-data-tools-business-intelligence-for-visual-studio-2013-ssdt-bi.aspx">AS team blog</a>. For support of SSDT-BI, please post to their blog or <a href="https://social.msdn.microsoft.com/Forums/sqlserver/en-US/home?forum=sqlanalysisservices">AS forums</a>.</p>
<p><a href="https://www.microsoft.com/download/details.aspx?id=36843"><span style="color: #0000ff;">Download SSDT-BI for Visual Studio 2012</span></a></p>
<p><a href="https://www.microsoft.com/download/details.aspx?id=42313"><span style="color: #0000ff;">Download SSDT-BI for Visual Studio 2013</span></a></p></blockquote>
<p>This is the option that most SQL Server DBAs and developers are going to need to download and install. If you don’t have a licensed copy of Visual Studio 2012 or 2013 this is what you need.</p>
<h3>Still Confused?</h3>
<p>Just download <a href="https://www.microsoft.com/en-us/download/details.aspx?id=42313"><span style="color: #0000ff;">SSDT-BI</span></a> and be done with it. If you already have Visual Studio 2013 but don’t have the BI projects, they’ll be added. If you don’t have Visual Studio 2013, you’ll get the SSDT version of it with just the BI projects.</p>
<p>The post <a href="https://sqlsolutionsgroup.com/sql-server-data-tools/">What happened to SQL Server Data Tools in SQL Server 2014?</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Social distancing in IT: Five tips to make working from home work for you</title>
		<link>https://sqlsolutionsgroup.com/working-from-home/</link>
		
		<dc:creator><![CDATA[Randy Knight]]></dc:creator>
		<pubDate>Wed, 18 Mar 2020 08:25:00 +0000</pubDate>
				<category><![CDATA[SQL Group]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[#microsftcertifedmaster]]></category>
		<category><![CDATA[#microsftpartner]]></category>
		<category><![CDATA[#SQLAB]]></category>
		<category><![CDATA[#SQlatino]]></category>
		<category><![CDATA[#SQlatinoamerica]]></category>
		<category><![CDATA[#sqldatabase]]></category>
		<category><![CDATA[#sqldeveloper]]></category>
		<category><![CDATA[#SQLgroupie]]></category>
		<category><![CDATA[#sqlimer]]></category>
		<category><![CDATA[#sqlimerbymay]]></category>
		<category><![CDATA[#sqlinjection]]></category>
		<category><![CDATA[#sqlinternals]]></category>
		<category><![CDATA[#sqlite]]></category>
		<category><![CDATA[#sqlite3]]></category>
		<category><![CDATA[#SQLLearning]]></category>
		<category><![CDATA[#SQLMagazine]]></category>
		<category><![CDATA[#sqlmanagementstudio]]></category>
		<category><![CDATA[#sqlmanager]]></category>
		<category><![CDATA[#Sqlmap]]></category>
		<category><![CDATA[#sqlrun]]></category>
		<category><![CDATA[#sqlsaturday2017]]></category>
		<category><![CDATA[#sqlsatvienna]]></category>
		<category><![CDATA[#sqlserver]]></category>
		<category><![CDATA[#SQLserver2012]]></category>
		<category><![CDATA[#sqlserver2014]]></category>
		<category><![CDATA[#sqlserver2017]]></category>
		<category><![CDATA[#sqlserver2022]]></category>
		<category><![CDATA[#SQLServeronLinux]]></category>
		<category><![CDATA[#SQLsolutionsgroup]]></category>
		<category><![CDATA[#SQLTraining]]></category>
		<category><![CDATA[#SQLYog]]></category>
		<category><![CDATA[COVID-19]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLPASS]]></category>
		<category><![CDATA[SQLSaturday]]></category>
		<category><![CDATA[SSG]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Work from home]]></category>
		<guid isPermaLink="false">https://sqlsolutionsgroup.com/?p=4610</guid>

					<description><![CDATA[<p>The post <a href="https://sqlsolutionsgroup.com/working-from-home/">Social distancing in IT: Five tips to make working from home work for you</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>So, it&#8217;s here: a global pandemic impacting billions around the globe and changing the ways we live, work, and interact with each other. Our new normal, for an unknown length of time, is all about social distancing and that means working from home for many of us.</p>
<p><a href="https://sqlsolutionsgroup.com/wp-content/uploads/2020/03/WFH.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-4611" src="https://sqlsolutionsgroup.com/wp-content/uploads/2020/03/WFH.jpg" alt="working from home" width="850" height="567" srcset="https://sqlsolutionsgroup.com/wp-content/uploads/2020/03/WFH.jpg 850w, https://sqlsolutionsgroup.com/wp-content/uploads/2020/03/WFH-300x200.jpg 300w, https://sqlsolutionsgroup.com/wp-content/uploads/2020/03/WFH-768x512.jpg 768w" sizes="(max-width: 850px) 100vw, 850px" /></a></p>
<p>At SSG, this is nothing new to us, and many IT professionals are well acquainted with working remotely. We&#8217;ve been a virtual company for our nearly 10-year history. Currently, our team is literally coast-to-coast: Seattle, L.A., Las Vegas (or even Mexico, making us international), and Orlando.</p>
<p>We&#8217;re sharing five best practices tips from our deep experience to make this new adventure work for you. </p>
<ol>
<li><strong>Make sure you&#8217;re working from home, and not living at work</strong>. Out of a sense of duty or obligation, you may be tempted to work more than usual, to drag out your workday longer than you really need to. You might think, &#8220;It&#8217;s 8 p.m., but I can just take a minute to answer this email,&#8221; or &#8220;I can bang out this task in a second.&#8221; While well-intentioned, it can lead to burn out. Avoid &#8220;living at work&#8221; by setting boundaries — boundaries that protect your employer&#8217;s time as well as your personal time.</li>
<li><strong>Establish a routine to make your work day as normal as possible</strong>. A consistent routine will help you with those boundaries. Get up at the normal time, start your day the way you usually do (as far as possible&#8230;going to the gym is likely out of the question), and be at your desk (as it were) at the regular time. I love the idea of getting dressed for work, and when work is over, go casual like you normally would. Take a lunch break, go for a walk, do something to get away from your desk for a few minutes every hour. After all, at work you&#8217;re not chained to your desk, so don&#8217;t behave that way while working at home. </li>
<li><strong>Claim and define your workspace</strong>. Working from home likely means you won&#8217;t be alone. For psychological as well as practical reasons, it&#8217;s important to have a defined area for work. If you don&#8217;t have a home office, you may have to improvise. High traffic areas like the kitchen and living room are poor options, so you may have to stick to your bedroom. Wherever it is, let your family know what when you&#8217;re &#8220;at work,&#8221; you&#8217;re at work, and disturbances should be kept to a minimum. A closed door should also signify &#8220;do not disturb&#8221; when needed. </li>
<li><strong>Use the tools that facilitate remote work</strong>. As IT professionals, we are (or should be) well versed in the tools that make working from home as seamless as possible. Tools like Asana, Jira, Zoom, Slack and Microsoft Teams are indispensable to keeping the collaboration, communication, and project management moving forward. Hopefully you and your organization are already established with one or more of these (or similar) and you don&#8217;t need a crash course in how to use them. If not, maybe you need to establish yourself as a SME and get the ball rolling. And, bonus tip: Before you have a Zoom call or something similar, build in some time to ensure you&#8217;ve addressed any installation needs and that your camera, mic, and speakers are good to go. (By the way: did you see where the <a href="https://www.forbes.com/sites/alexkonrad/2020/03/13/zoom-video-coronavirus-eric-yuan-schools/#3da0fa754e71"><span style="text-decoration: underline;">CEO of Zoom is removing video conferencing time limits for K-12 schools</span></a> in Japan, Italy and the U.S.? Well done, Eric Yuan.)</li>
<li><strong>Take a deep breath</strong>. If working from home is new to you, give yourself time to adjust. Many others are in the same boat and will give you the benefit of the doubt. If you&#8217;re on a conference call and the dog barks (it will happen), don&#8217;t freak out. Use good etiquette and common sense in your on-line interactions, but remember that real life will continue to happen. Here&#8217;s a good way to cope with the stresses of our new reality: If you usually have a lengthy commute, fill up that time with some reading, exercise, catnap or something else that helps you clear your head. </li>
</ol>
<p>I&#8217;ve seen some commentators suggest that the necessity of employees working from home now will lead to many companies increasingly  transition to such an arrangement following the pandemic. I won&#8217;t go that far, but it&#8217;s true that IT work in general and database management in particular is highly compatible with working remote. </p>
<p>Regardless of how long this lasts for you, making it feel as normal as possible will be a key to how successful your time away from the office goes. I&#8217;d love to hear how you&#8217;re making it work for you, so leave your comments. </p>
<p>The post <a href="https://sqlsolutionsgroup.com/working-from-home/">Social distancing in IT: Five tips to make working from home work for you</a> appeared first on <a href="https://sqlsolutionsgroup.com">SQL Solutions Group</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
