<?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>David Barbarin &#187; SQL Server 2012</title>
	<atom:link href="https://blog.developpez.com/mikedavem/pcategory/sql-server-2012/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/mikedavem</link>
	<description>MVP DataPlatform - MCM SQL Server</description>
	<lastBuildDate>Thu, 09 Sep 2021 21:19:50 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>SQL Server index rebuid online and blocking scenario</title>
		<link>https://blog.developpez.com/mikedavem/p13199/sql-server-2012/sql-server-index-rebuid-online-and-blocking-scenario</link>
		<comments>https://blog.developpez.com/mikedavem/p13199/sql-server-2012/sql-server-index-rebuid-online-and-blocking-scenario#comments</comments>
		<pubDate>Sun, 30 Aug 2020 21:18:28 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[SQL Server 2019]]></category>
		<category><![CDATA[blocking]]></category>
		<category><![CDATA[online operation]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1664</guid>
		<description><![CDATA[A couple of months ago, I experienced a problem about index rebuild online operation on SQL Server. In short, the operation was supposed to be online and to never block concurrent queries. But in fact, it was not the case &#8230; <a href="https://blog.developpez.com/mikedavem/p13199/sql-server-2012/sql-server-index-rebuid-online-and-blocking-scenario">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A couple of months ago, I experienced a problem about index rebuild online operation on SQL Server. In short, the operation was supposed to be online and to never block concurrent queries. But in fact, it was not the case (or to be more precise, it was partially the case) and to make the scenario more complex, we experienced different behaviors regarding the context. Let’s start the story with the initial context: in my company, we usually go through continuous deployment including SQL modification scripts and because we usually rely on daily pipeline, we must ensure related SQL operations are not too disruptive to avoid impacting the user experience.</p>
<p><span id="more-1664"></span></p>
<p>Sometimes, we must introduce new indexes to deployment scripts and according to how disruptive the script can be, a discussion between Devs and Ops is initiated, and it results either to manage manually by the Ops team or to deploy it automatically through the automatic deployment pipeline by Devs. </p>
<p>Non-disruptive operations can be achieved in many ways and ONLINE capabilities of SQL Server may be part of the solution and this is what I suggested with one of our scripts. Let’s illustrate this context with the following example. I created a table named dbo.t1 with a bunch of rows:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">USE [test];<br />
<br />
SET NOCOUNT ON;<br />
<br />
DROP TABLE IF EXISTS dbo.t1;<br />
GO<br />
<br />
CREATE TABLE dbo.t1 (<br />
&nbsp; &nbsp; id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,<br />
&nbsp; &nbsp; col1 VARCHAR(50) NULL<br />
);<br />
GO<br />
<br />
INSERT INTO dbo.t1 (col1) VALUES (REPLICATE('T', 50));<br />
GO …<br />
EXEC sp_spaceused 'dbo.t1'<br />
--name&nbsp; rows&nbsp; &nbsp; reserved&nbsp; &nbsp; data&nbsp; &nbsp; index_size&nbsp; unused<br />
--t1&nbsp; &nbsp; 5226496 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1058000 KB&nbsp; 696872 KB &nbsp; 342888 KB &nbsp; 18240 KB</div></div>
<p>Go ahead and let’ set the context with a pattern of scripts deployment we went through during this specific deployment. Let’s precise this script is over simplified, but I keep the script voluntary simple to focus only on the most important part.  You will notice the script includes two steps with operations on the same table including updating / fixing values in col2 first and then rebuilding index on col1.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">/* Code before */<br />
<br />
-- Update some values in the col1 colum<br />
UPDATE [dbo].[t1]<br />
SET col1 = REPLICATE('B', 50)<br />
<br />
-- Then create an index on col1 column<br />
CREATE INDEX [col1]<br />
ON [dbo].[t1] (col1) WITH (ONLINE = ON);<br />
GO</div></div>
<p>At the initial stage, the creation of index was by default (OFFLINE). Having discussed this point with the DEV team, we decided to create the index ONLINE in this context. The choice between OFFLINE / ONLINE operation is often not trivial and should be evaluated carefully but to keep simple, let’s say it was the right way to go in our context. Generally speaking, online operations are slower, but the tradeoff was acceptable in order to minimize blocking issues during this deployment. At least, this is what I thought …</p>
<p>In my demo, without any concurrent workload against the dbo.t1 table, creating the index offline took 6s compared to the online method with 12s. So, an expected result here …</p>
<p>Let’s run this another query in another session:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT id, col1<br />
FROM dbo.t1<br />
WHERE id BETWEEN 1 AND 2</div></div>
<p>In a normal situation, this query should be blocked in a short time corresponding to the duration of the update operation. But once the update is done, blocking situation should disappear even during the index rebuild operation that is performed ONLINE. </p>
<p>But now let’s add <a href="https://flywaydb.org/" rel="noopener" target="_blank">Flyway</a> to the context. Flyway is an open source tool we are using for automatic deployment of SQL objects. The deployment script was executed from it in ACC environment and we noticed longer blocked concurrent accesses this time. This goes against what we would ideally like. Digging through this issue with the DEV team, we also noticed the following message when running the deployment script:</p>
<p><em>Warning: Online index operation on table &lsquo;dbo.t1 will proceed but concurrent access to the table may be limited due to residual lock on the table from a previous operation in the same transaction.<br />
</em></p>
<p>This is something I didn’t noticed from SQL Server Management Studio when I tested the same deployment script. So, what happened here?</p>
<p>Referring to the <a href="https://flywaydb.org/documentation/migrations#transactions" rel="noopener" target="_blank">Flyway documentation</a>, it is mentioned that Flyway always wraps the execution of an entire migration within a single transaction by default and it was exactly the root cause of the issue.</p>
<p>Let’s try with some experimentations: </p>
<p><strong>Test 1</strong>: Update + rebuilding index online in implicit transaction mode (one transaction per query).</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">-- Update some values in the col1 colum<br />
UPDATE [dbo].[t1]<br />
SET col1 = REPLICATE('B', 50)<br />
<br />
-- Then create an index on col1 column<br />
CREATE INDEX [col1]<br />
ON [dbo].[t1] (col1) WITH (ONLINE = ON);<br />
GO<br />
-- In another session<br />
SELECT id, col1<br />
FROM dbo.t1<br />
WHERE id BETWEEN 1 AND 2</div></div>
<p><strong>Test 2</strong>: Update + rebuilding index online within one single explicit transaction</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">BEGIN TRAN;<br />
<br />
-- Update some values in the col1 colum<br />
UPDATE [dbo].[t1]<br />
SET col1 = REPLICATE('B', 50)<br />
<br />
-- Then create an index on col1 column<br />
CREATE INDEX [col1]<br />
ON [dbo].[t1] (col1) WITH (ONLINE = ON);<br />
GO<br />
COMMIT TRAN;<br />
-- In another session<br />
SELECT id, col1<br />
FROM dbo.t1<br />
WHERE id BETWEEN 1 AND 2</div></div>
<p>After running these two scripts, we can notice the blocking duration of SELECT query is longer in test2 as shown in the picture below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/166-1-blocked-process.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/166-1-blocked-process.jpg" alt="166 - 1 - blocked process" width="890" height="358" class="alignnone size-full wp-image-1665" /></a></p>
<p>In the test 1, the duration of the blocking session corresponds to that for updating operation (first step of the script). However, in the test 2, we must include the time for creating the index but let’s precise the index is not the blocking operation at all, but it increases the residual locking put by the previous update operation. In short, this is exactly what the warning message is telling us. I think you can imagine easily which impact such situation may implies if the index creation takes a long time. You may get exactly the opposite of what you really expected. </p>
<p>Obviously, this is not a recommended situation and creating an index should be run in very narrow and constrained transaction.But from my experience, things are never always obvious and regarding your context, you should keep an eye of how transactions are managed especially when it comes automatic deployment stuff that could be quickly out of the scope of the DBA / Ops team. Strong collaboration with DEV team is recommended to anticipate this kind of issue.</p>
<p>See you !!</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Monitoring Azure SQL Databases with Azure Monitor and Automation</title>
		<link>https://blog.developpez.com/mikedavem/p13198/sql-server-2012/monitoring-azure-sql-databases-with-azure-monitor-and-automation</link>
		<comments>https://blog.developpez.com/mikedavem/p13198/sql-server-2012/monitoring-azure-sql-databases-with-azure-monitor-and-automation#comments</comments>
		<pubDate>Sun, 23 Aug 2020 15:32:07 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Azure]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Alerts]]></category>
		<category><![CDATA[Azure Monitor]]></category>
		<category><![CDATA[Azure SQL Database]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1653</guid>
		<description><![CDATA[Supervising Cloud Infrastructure is an important aspect of Cloud administration and Azure SQL Databases are no exception. This is something we are continuously improving at my company. On-prem, DBAs often rely on well-established products but with Cloud-based architectures, often implemented &#8230; <a href="https://blog.developpez.com/mikedavem/p13198/sql-server-2012/monitoring-azure-sql-databases-with-azure-monitor-and-automation">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Supervising Cloud Infrastructure is an important aspect of Cloud administration and Azure SQL Databases are no exception. This is something we are continuously improving at my company. </p>
<p>On-prem, DBAs often rely on well-established products but with Cloud-based architectures, often implemented through DevOps projects and developers, monitoring should be been redefined and include some new topics as:</p>
<p><span id="more-1653"></span></p>
<p>1)	Cloud service usage and fees observability<br />
2)	Metrics and events detection that could affect bottom line<br />
3)	Implementing a single platform to report all data that comes from different sources<br />
4)	Trigger rules with data if workload reaches over or drops below certain levels or when an event is enough relevant to not meet the configuration standard and implies unwanted extra billing or when it compromises the company security rules.<br />
5)	Monitoring of the user experience</p>
<p>A key benefit often discussed about Cloud computing, and mainly driven by DevOps, is how it enables agility. One of the meaning of term agility is tied to the rapid provisioning of computer resources (in seconds or minutes) and this shortening provisioning path enables work to start quickly. You may be tempted to grant some provisioning permissions to DEV teams and from my opinion this is not a bad thing, but it may come with some drawbacks if not under control by Ops team including database area. Indeed, for example I have in mind some real cases including architecture configuration drift, security breaches created by unwanted item changes, or idle orphan resources for which you keep being charged. All of these scenarios may lead either to security issues or extra billing and I believe it is important to get clear visibility of such events. </p>
<p>In my company, Azure built-in capabilities with Azure Monitor architecture are our first target (at least in a first stage) and seem to address the aforementioned topics. To set the context, we already relied on Azure Monitor infrastructure for different things including Query Performance Insight, SQL Audit analysis through Log Analytics and Azure alerts for some performance metrics. Therefore, it was the obvious way to go further by adding activity log events to the story. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/165-1-Azure-Monitor.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/165-1-Azure-Monitor.jpg" alt="165 - 1 - Azure Monitor" width="843" height="474" class="alignnone size-full wp-image-1655" /></a></p>
<p>In this blog post, let’s focus on the items 2) 4). I would like to share some experimentations and thoughts about them. As a reminder, items 2) 4) are about catching relevant events to help identifying configuration and security drifts and performing actions accordingly. In addition, as many event-based architectures, additional events may appear or evolve over the time and we started thinking about the concept with the following basic diagram …</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/165-2-Workflow-chart-e1598182358607.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/165-2-Workflow-chart-e1598182358607.jpg" alt="165 - 2 - Workflow chart" width="800" height="533" class="alignnone size-full wp-image-1657" /></a></p>
<p>… that led to the creation of the two following workflows:<br />
&#8211;	Workflow 1: To get notified immediately for critical events that may compromise security or lead immediately to important extra billing<br />
&#8211;	Workflow 2: To get a report of other misconfigured items (including critical ones) on schedule basis but don’t require quick responsiveness of Ops team.</p>
<p>Concerning the first workflow, using <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/platform/activity-log-alerts" rel="noopener" target="_blank">alerts on activity logs</a>, action groups and webhooks as input of an Azure automation runbook appeared to be a good solution. On another side, the second one only requires running an Azure automation workbook on schedule basis. In fact, this is the same runbook but with different input parameters according to the targeted environment (e.g. PROD / ACC / INT). In addition, the runbook should be able to identity unmanaged events and notified Ops team who will decide either to skip it or to integrate it to runbook processing.</p>
<p>Azure alerts which can be divided in different categories including metric, log alerts and activity log alerts. The last one drew our attention because it allows getting notified for operation of specific resources by email or by generating JSON schema reusable from Azure Automation runbook. Focusing on the latter, we had come up (I believe) with what we thought was a reasonable solution. </p>
<p>Here the high-level picture of the architecture we have implemented:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/165-3-Architecture-e1598182462929.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/165-3-Architecture-e1598182462929.jpg" alt="165 - 3 - Architecture" width="800" height="347" class="alignnone size-full wp-image-1659" /></a></p>
<p>1-	During the creation of an Azure SQL Server or a database, corresponding alerts are added with Administrative category with a specific scope. Let&rsquo;s precise that concerned operations must be registered with Azure Resource Manager in order to be used in Activity Log and fortunately they are all including in the <a href="https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations" rel="noopener" target="_blank">Microsoft.Sql</a> resource provider in this case.<br />
2-	When an event occurs on the targeted environment, an alert is triggered as well as the concerned runbook.<br />
3-	The execution of the same runbook but with different input parameters is scheduled on weekly basis to a general configuration report of our Azure SQL environments.<br />
4-	According the event, Ops team gets notified and acts (either to update misconfigured item, or to delete the unauthorized item, or to update runbook code on Git Repo to handle the new event and so on …)</p>
<p>The skeleton of the Azure automation runbook is pretty similar to the following one:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;height:450px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[OutputType(&quot;PSAzureOperationResponse&quot;)]<br />
param<br />
(<br />
&nbsp; &nbsp; [Parameter (Mandatory=$false)]<br />
&nbsp; &nbsp; [object] $WebhookData<br />
&nbsp; &nbsp; ,<br />
&nbsp; &nbsp; [parameter(Mandatory=$False)]<br />
&nbsp; &nbsp; [ValidateSet(&quot;PROD&quot;,&quot;ACC&quot;,&quot;INT&quot;)]<br />
&nbsp; &nbsp; [String]$EnvTarget<br />
&nbsp; &nbsp; ,<br />
&nbsp; &nbsp; [parameter(Mandatory=$False)]<br />
&nbsp; &nbsp; [Boolean]$DebugMode = $False<br />
)<br />
<br />
<br />
<br />
<br />
If ($WebhookData)<br />
{<br />
<br />
&nbsp; &nbsp; # Logic to allow for testing in test pane<br />
&nbsp; &nbsp; If (-Not $WebhookData.RequestBody){<br />
&nbsp; &nbsp; &nbsp; &nbsp; $WebhookData = (ConvertFrom-Json -InputObject $WebhookData)<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; $WebhookBody = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)<br />
<br />
&nbsp; &nbsp; $schemaId = $WebhookBody.schemaId<br />
<br />
&nbsp; &nbsp; If ($schemaId -eq &quot;azureMonitorCommonAlertSchema&quot;) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; # This is the common Metric Alert schema (released March 2019)<br />
&nbsp; &nbsp; &nbsp; &nbsp; $Essentials = [object] ($WebhookBody.data).essentials<br />
&nbsp; &nbsp; &nbsp; &nbsp; # Get the first target only as this script doesn't handle multiple<br />
&nbsp; &nbsp; &nbsp; &nbsp; $status = $Essentials.monitorCondition<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; # Focus only on succeeded or Fired Events<br />
&nbsp; &nbsp; &nbsp; &nbsp; If ($status -eq &quot;Succeeded&quot; -Or $Status -eq &quot;Fired&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Extract info from webook <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $alertTargetIdArray = (($Essentials.alertTargetIds)[0]).Split(&quot;/&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $SubId = ($alertTargetIdArray)[2]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ResourceGroupName = ($alertTargetIdArray)[4]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ResourceType = ($alertTargetIdArray)[6] + &quot;/&quot; + ($alertTargetIdArray)[7]<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Determine code path depending on the resourceType<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ($ResourceType -eq &quot;microsoft.sql/servers&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # DEBUG<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;This is a SQL Server Resource.&quot;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $firedDate = $Essentials.firedDateTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $AlertContext = [object] ($WebhookBody.data).alertContext<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $channel = $AlertContext.channels<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $EventSource = $AlertContext.eventSource<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Level = $AlertContext.level<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation = $AlertContext.operationName<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Properties = [object] ($WebhookBody.data).alertContext.properties<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $EventName = $Properties.eventName<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $EventStatus = $Properties.status<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Description = $Properties.description_scrubbed<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Caller = $Properties.caller<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $IPAddress = $Properties.ipAddress<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ResourceName = ($alertTargetIdArray)[8]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $DatabaseName = ($alertTargetIdArray)[10]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation_detail = $Operation.Split('/')<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Check firewall rules<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If ($EventName -eq 'OverwriteFirewallRules'){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Firewall Overwrite is detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle firewall update event<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Update DB =&amp;gt; No need to be monitored in real time<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($EventName -eq 'UpdateDatabase') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database config update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Create DB<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($EventName -eq 'CreateDatabase' -Or `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation -eq 'Microsoft.Sql/servers/databases/write'){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database creation has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database creation event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Delete DB<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($EventName -eq 'DeleteDatabase' -Or `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation -eq 'Microsoft.Sql/servers/databases/delete') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database has been deleted ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database deletion event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($Operation -eq 'Microsoft.Sql/servers/databases/transparentDataEncryption/write') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database Encryption update has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database encryption update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($Operation -eq 'Microsoft.Sql/servers/databases/auditingSettings/write') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database Audit update has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database audit update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($Operation -eq 'Microsoft.Sql/servers/databases/securityAlertPolicies/write' -or $Operation -eq 'Microsoft.Sql/servers/databases/vulnerabilityAssessments/write') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure ADS update has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle ADS update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ElseIf ($Operation -eq 'Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies/write'){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Retention Backup has been modified ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database retention backup update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # ... other ones <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Event not managed yet &nbsp; &nbsp;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # ResourceType not supported<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Error &quot;$ResourceType is not a supported resource type for this runbook.&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; Else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # The alert status was not 'Activated' or 'Fired' so no action taken<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Verbose (&quot;No action taken. Alert status: &quot; + $status) -Verbose<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; Else{<br />
&nbsp; &nbsp; &nbsp; &nbsp;# SchemaID doesn't correspond to azureMonitorCommonAlertSchema =&amp;gt;&amp;gt; Skip<br />
&nbsp; &nbsp; &nbsp; &nbsp;Write-Host &quot;Skip ...&quot; <br />
&nbsp; &nbsp; }<br />
}<br />
Else {<br />
&nbsp; &nbsp; Write-Output &quot;No Webhook detected ... switch to normal mode ...&quot;<br />
<br />
&nbsp; &nbsp; If ([String]::IsNullOrEmpty($EnvTarget)){<br />
&nbsp; &nbsp; &nbsp; &nbsp; Write-Error '$EnvTarget is mandatory in normal mode'<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; #########################################################<br />
&nbsp; &nbsp; # Code for a complete check of Azure SQL DB environment #<br />
&nbsp; &nbsp; #########################################################<br />
}</div></div>
<p>Some comments about the PowerShell script:</p>
<p>1)	Input parameters should include either the Webhook data or specific parameter values for a complete Azure SQL DB check.<br />
2)	The first section should include your own functions to respond to different events. In our context, currently we drew on <a href="https://github.com/sqlcollaborative/dbachecks" rel="noopener" target="_blank">DBAChecks</a> thinking to develop a derived model but why not using directly DBAChecks in a near future?<br />
3)	When an event is triggered, a JSON schema is generated and provides insight. The point here is you must navigate through different properties according to the operation type (cf. <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/platform/activity-log-schema" rel="noopener" target="_blank">BOL</a>).<br />
4)	The increase of events to manage could be a potential issue making the runbook fat especially if we keep both the core functions and event processing. To mitigate this topic, we are thinking to move functions into modules in Azure automation (next step).</p>
<p><strong>Bottom line</strong></p>
<p>Thanks to Azure built-in capabilities we improved our visibility of events that occur on the Azure SQL environment (both expected and unexcepted) and we’re now able to act accordingly. But I should tell you that going this way is not a free lunch and we achieved a reasonable solution after some programming and testing efforts. If you can invest time, it is probably the kind of solution you can add to your study.</p>
<p>See you</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dealing with SQL Server on Linux on WSL2</title>
		<link>https://blog.developpez.com/mikedavem/p13196/sql-server-2012/dealing-with-sql-server-on-linux-on-wsl2</link>
		<comments>https://blog.developpez.com/mikedavem/p13196/sql-server-2012/dealing-with-sql-server-on-linux-on-wsl2#comments</comments>
		<pubDate>Mon, 27 Jul 2020 06:53:32 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[Init]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[sqlserver]]></category>
		<category><![CDATA[start-stop-daemon]]></category>
		<category><![CDATA[WSL]]></category>
		<category><![CDATA[WSL2]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1626</guid>
		<description><![CDATA[This is a blog post I intended to write sometime ago &#8230; about using SQL Server on Linux on WSL2. For whom already installed it on Windows 10, version 2004, you are already aware it doesn’t come with the support &#8230; <a href="https://blog.developpez.com/mikedavem/p13196/sql-server-2012/dealing-with-sql-server-on-linux-on-wsl2">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>This is a blog post I intended to write sometime ago &#8230; about using SQL Server on Linux on WSL2. For whom already installed it on Windows 10, version 2004, you are already aware it doesn’t come with the support of systemd. Indeed, although it does exist in the file system, systemd is not running. If you intend to use directly SQL Server on WSL2, you need to read this carefully, because installation and management relies precisely on systemd!</p>
<p><span id="more-1626"></span></p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-0-banner.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-0-banner.jpg" alt="163 - 0 - banner" width="508" height="187" class="alignnone size-full wp-image-1639" /></a></p>
<p>First, let&rsquo;s say if you want to run SQL Server on WSL2 in a supported way, docker containers remain probably the better fit. Podman may be also an alternative but it seems to remain an experimental stuff so far. The interesting point is that some people prefer to use Docker directly on WSL2 whereas other ones prefer to use Docker Desktop for Windows with the integration of WSL2 based engine. The option seems to be available for a few months as shown below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-1-Docker-Desktop-WSL2.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-1-Docker-Desktop-WSL2.jpg" alt="163 - 1 - Docker Desktop WSL2" width="824" height="495" class="alignnone size-full wp-image-1627" /></a></p>
<p>But this is not the main topic of this blog post. Having interesting discussions with some of my colleagues, we wanted to know if we were able to install directly SQL Server on WSL2 and the good news is we finally managed to do it but at the cost of some (dirty) tricks required to make SQL Server starting / stopping correctly.</p>
<p>Before continuing, let’s precise we did it in a <strong>pure experimental and academic way</strong> and this is definitely <strong>not supported by Microsoft</strong>. But before starting my holidays in August, it was something very fun and a good reminder of some Linux concepts … </p>
<p>I did my test with the Ubuntu-18.04 distro in WSL v2.</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-2-WSL2-Ubuntu18.04.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-2-WSL2-Ubuntu18.04.jpg" alt="163 - 2 - WSL2 Ubuntu18.04" width="387" height="86" class="alignnone size-full wp-image-1629" /></a></p>
<p>First step consisted in installing SQL Server in an usual way as per the <a href="https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-ubuntu?view=sql-server-ver15" rel="noopener" target="_blank">Microsoft BOL</a>. The installation was done correctly but after running the setup, an error message raised quickly in the last step related to service initialization:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-3-install-sql.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-3-install-sql.jpg" alt="163 - 3 - install sql" width="716" height="96" class="alignnone size-full wp-image-1630" /></a></p>
<p>In fact, if you think about it, this message is expected because systemd is not running on WSL2 and the configuration process attempts to initialize the mssql-server service based on systemd. But let&rsquo;s dig further on the installation process &#8230; Referring to how a deb package is made, there exist preinst, postinst, prerm, postrm scripts for mssqlserver deb package located in <strong>/var/lib/dpkg/info/</strong>:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ sudo ls -l /var/lib/dpkg/info/mssql-server*<br />
-rwxr-xr-x 1 root root &nbsp; 108 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.config<br />
-rw-r--r-- 1 root root &nbsp;8579 Jul 26 00:31 /var/lib/dpkg/info/mssql-server.list<br />
-rw-r--r-- 1 root root 11543 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.md5sums<br />
-rwxr-xr-x 1 root root &nbsp;1436 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.postinst<br />
-rwxr-xr-x 1 root root &nbsp; 289 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.postrm<br />
-rwxr-xr-x 1 root root &nbsp;1353 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.preinst<br />
-rwxr-xr-x 1 root root &nbsp; 365 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.prerm<br />
-rw-r--r-- 1 root root &nbsp; &nbsp;72 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.shlibs<br />
-rw-r--r-- 1 root root &nbsp; 305 Jun 16 20:00 /var/lib/dpkg/info/mssql-server.templates<br />
-rw-r--r-- 1 root root &nbsp; &nbsp;74 Jun 16 20:01 /var/lib/dpkg/info/mssql-server.triggers</div></div>
<p>My suspicion was those files content references of systemctl commands and yes, there were in preinst/prerm/postins/prerm files:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-4-install-files-and-systemctl-dependencies-e1595827795971.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-4-install-files-and-systemctl-dependencies-e1595827795971.jpg" alt="163 - 4 - install files and systemctl dependencies" width="800" height="170" class="alignnone size-full wp-image-1631" /></a></p>
<p>Well, we found a reasonable explanation of the previous error message at least. At this stage, I would say you can use your new fresh installed SQL Server instance, but it requires to manually start / stop it because there are no systemctl commands to handle it. But thinking about it … we are still using the famous init daemon (PID1) on WSL2 and it works for regular services. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-5-top-tree-init.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-5-top-tree-init.jpg" alt="163 - 5 - top tree init" width="812" height="142" class="alignnone size-full wp-image-1632" /></a></p>
<p>A good alternative could be to rely on init scripts and <a href="on start-stop-daemon wrapped into LSB-compliant init scripts with" rel="noopener" target="_blank">start-stop-daemon</a> wrapped into LSB-compliant init scripts with:</p>
<p>&#8211;	At least start, stop, restart, force-reload, and status<br />
&#8211;	Return Proper exit code<br />
&#8211;	Document run-time dependencies</p>
<p>LSB provides default set of functions which is in <strong>/lib/lsb/init-functions</strong> and we can make use of those functions in our Init scripts. The script file is located to <strong>/etc/init.d</strong> and named mssql-server.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ sudo ls -l /etc/init.d/mssql*<br />
-rwxr-xr-x 1 root root 1606 Jul 26 22:13 /etc/init.d/mssql-server</div></div>
<p>Here the content of my mssql-server script file:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;height:450px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#! /bin/sh -e<br />
#<br />
### BEGIN INIT INFO<br />
# Provides: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sqlserver<br />
# Required-Start: &nbsp; &nbsp;$all<br />
# Required-Stop:<br />
# Default-Start: &nbsp; &nbsp; 2 3 4 5<br />
# Default-Stop: &nbsp; &nbsp; &nbsp;0 1 6<br />
# Short-Description: Manages SQL Server instance on Linux<br />
### END INIT INFO<br />
<br />
DAEMON=&quot;/opt/mssql/bin/sqlservr&quot;<br />
daemon_OPT=&quot;&quot;<br />
DAEMONUSER=&quot;mssql&quot;<br />
daemon_NAME=&quot;sqlservr&quot;<br />
<br />
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/var/opt/mssql<br />
<br />
# Check sqlserver is present<br />
if [ ! -x $DAEMON ]; then<br />
&nbsp; &nbsp; &nbsp; &nbsp; log_failure_msg &quot;$DAEMON not present or not executable&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; exit 1<br />
fi<br />
<br />
# Load init functions<br />
. /lib/lsb/init-functions<br />
<br />
<br />
d_start () {<br />
&nbsp; &nbsp; &nbsp; &nbsp; log_daemon_msg &quot;Starting system $daemon_NAME Daemon&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; start-stop-daemon --background --name $daemon_NAME --start --quiet --chuid $DAEMONUSER --exec $DAEMON --umask 007 -- $DAEMON_OPTS --oknodo<br />
&nbsp; &nbsp; &nbsp; &nbsp; log_end_msg $?<br />
}<br />
<br />
d_stop () {<br />
&nbsp; &nbsp; &nbsp; &nbsp; log_daemon_msg &quot;Stopping system $daemon_NAME Daemon&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; start-stop-daemon --name $daemon_NAME --stop --retry 5 --quiet --name $daemon_NAME --oknodo<br />
&nbsp; &nbsp; &nbsp; &nbsp; log_end_msg $?<br />
}<br />
<br />
case &quot;$1&quot; in<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; start|stop)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d_${1}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; restart|reload|force-reload)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d_stop<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d_start<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; force-stop)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;d_stop<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; status)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status_of_proc &quot;$daemon_NAME&quot; &quot;$DAEMON&quot; &quot;system-wide $daemon_NAME&quot; &amp;amp;&amp;amp; exit 0 || exit $?<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;;<br />
&nbsp; &nbsp; &nbsp; &nbsp; *)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; echo &quot;Usage: /etc/init.d/$daemon_NAME {start|stop|force-stop|restart|reload|force-reload|status}&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exit 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;;<br />
esac<br />
exit 0</div></div>
<p>Thus, I was now able to manage with status / start / stop / restart operations:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ sudo service mssql-server status<br />
&nbsp;/opt/mssql/bin/sqlservr is not running<br />
$ sudo service mssql-server start<br />
&nbsp;Starting system sqlservr Daemon &nbsp; &nbsp; &nbsp; &nbsp; [ OK ]</div></div>
<p>The SQL Server engine was started successfully, and I can double check with the top command &#8230;</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-6-top-sqlservr-e1595828331414.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-6-top-sqlservr-e1595828331414.jpg" alt="163 - 6 - top sqlservr" width="800" height="303" class="alignnone size-full wp-image-1634" /></a></p>
<p>&#8230; and with a quick connect to my SQL Server instance:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-7-mssql-cli-e1595828387503.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-7-mssql-cli-e1595828387503.jpg" alt="163 - 7 - mssql-cli" width="800" height="257" class="alignnone size-full wp-image-1635" /></a></p>
<p>As starting my SQL Server instance, stopping it can be performed with the service command and stop:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ sudo service mssql-server stop<br />
&nbsp;Stopping system sqlservr Daemon &nbsp; &nbsp; &nbsp; &nbsp; [ OK ]<br />
<br />
$ sudo service mssql-server status<br />
/opt/mssql/bin/sqlservr is not running</div></div>
<p>Generally speaking, there is no concept of runlevel with WSL, so starting automatically the mssql-service with the WSL2 startup can be achieved in different ways with entries in .bashrc file or tricks from <a href="https://github.com/shayne/wsl2-hacks/blob/master/README.md" rel="noopener" target="_blank">github projects</a> (not tested from my side). </p>
<p>Finally, let’s talk about removing SQL Server from WSL2. As a reminder, during the installation / setup we faced an error message related to systemd. We also identified some dependencies to systemd in some dkpg files as shown below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/07/163-4-install-files-and-systemctl-dependencies-e1595827795971.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/07/163-4-install-files-and-systemctl-dependencies-e1595827795971.jpg" alt="163 - 4 - install files and systemctl dependencies" width="800" height="170" class="alignnone size-full wp-image-1631" /></a></p>
<p>Similar to the installation step, you will experience the same kind of issue with prerm / postrm files when removing SQL Server. In my case, I had to comment concerned lines in those files to uninstall successfully my SQL Server instance. </p>
<p>Hope this blog post helps! </p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>dbachecks and AlwaysOn availability group checks</title>
		<link>https://blog.developpez.com/mikedavem/p13194/sql-server-2012/dbachecks-and-alwayson-availability-group-checks</link>
		<comments>https://blog.developpez.com/mikedavem/p13194/sql-server-2012/dbachecks-and-alwayson-availability-group-checks#comments</comments>
		<pubDate>Mon, 20 Apr 2020 19:57:31 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[SQL Server 2019]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[dbachecks]]></category>
		<category><![CDATA[dbatools]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[sqlserver]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1591</guid>
		<description><![CDATA[When I started my DBA position in my new company, I was looking for a tool that was able to check periodically the SQL Server database environments for several reasons. First, as DBA one of my main concern is about &#8230; <a href="https://blog.developpez.com/mikedavem/p13194/sql-server-2012/dbachecks-and-alwayson-availability-group-checks">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>When I started my DBA position in my new company, I was looking for a tool that was able to check periodically the SQL Server database environments for several reasons. First, as DBA one of my main concern is about maintaining and keeping the different mssql environments well-configured against an initial standard. It is also worth noting I’m not the only person to interact with databases and anyone in my team, which is member of sysadmin server role as well, is able to change any server-level configuration settings at any moment. In this case, chances are that having environments shifting from our initial standard over the time and my team and I need to keep confident by checking periodically the current mssql environment configurations, be alerting if configuration drifts exist and obviously fix it as faster as possible.  </p>
<p><span id="more-1591"></span></p>
<p>A while ago, I relied on SQL Server Policy Based Management feature (PBM) to carry out this task at one of my former customers and I have to say it did the job but with some limitations. Indeed, PBM is the instance-scope feature and doesn’t allow to check configuration settings outside the SQL Server instance for example. During my investigation, <a href="https://dbachecks.readthedocs.io/en/latest/" rel="noopener" target="_blank">dbachecks</a> framework drew my attention for several reasons:</p>
<p>&#8211;	It allows to check different settings at different scopes including Operating System and SQL Server instance items<br />
&#8211;	It is an open source project and keeps evolving with SQL / PowerShell community contributions.<br />
&#8211;	It is extensible, and we may include custom checks to the list of predefined checks shipped with the targeted version.<br />
&#8211;	It is based on PowerShell, Pester framework and fits well with existing automation and GitOps process in my company</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/04/161-0-dbachecks-process.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/04/161-0-dbachecks-process.jpg" alt="161 - 0 - dbachecks process" width="1003" height="395" class="alignnone size-full wp-image-1592" /></a></p>
<p>The first dbacheck version we deployed in production a couple of month ago was 1.2.24 and unfortunately it didn’t include reliable tests for availability groups. It was the starting point of my first contributions to open source projects and I felt proud and got honored when I noticed my 2 PRs validated for the dbacheck tool including Test Disk Allocation Unit and Availability Group checks:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/04/161-1-release-note.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/04/161-1-release-note.jpg" alt="161 - 1 - release note" width="798" height="348" class="alignnone size-full wp-image-1593" /></a></p>
<p>Obviously, this is just an humble contribution and to be clear, I didn’t write the existing tests for AGs but I spent some times to apply fixes for a better detection of all AG environments including their replicas in a simple and complex topologies (several replicas on the same server and non-default ports for example). </p>
<p>So, here the current list of AG checks in the version 1.2.29 at the moment of this write-up:</p>
<p>&#8211;	Cluster node should be up<br />
&#8211;	AG resource + IP Address in the cluster should be online<br />
&#8211;	Cluster private and public network should be up<br />
&#8211;	HADR should be enabled on each AG replica<br />
&#8211;	AG Listener + AG replicas should be pingable and reachable from client connections<br />
&#8211;	AG replica should be in the correct domain name<br />
&#8211;	AG replica port number should be equal to the port specified in your standard<br />
&#8211;	AG availability mode should not be in unknown state and should be in synchronized or synchronizing state regarding the replication type<br />
&#8211;	Each high available database (member of an AG) should be in synchronized / synchronizing state, ready for failover, joined to the AG and not in suspended state<br />
&#8211;	Each AG replica should have an extended event session called AlwaysOn_health which is in running state and configured in auto start mode</p>
<p>Mandatory parameters are <strong>app.cluster</strong> and <strong>domain.name</strong>.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Get-DbcCheck -Tag HADR | ft Group, Type, AllTags, Config -AutoSize<br />
<br />
Group Type &nbsp; &nbsp; &nbsp; &nbsp;AllTags &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Config<br />
----- ---- &nbsp; &nbsp; &nbsp; &nbsp;------- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ------<br />
HADR &nbsp;ClusterNode ClusterHealth, HADR app.sqlinstance app.cluster skip.hadr.listener.pingcheck domain.name policy...</div></div>
<p>The starting point of the HADR checks is the Windows Failover Cluster component and hierarchically other tests are performed on each sub component including availability group, AG replicas and AG databases. </p>
<p>Then you may change the behavior on the HADR check process according to your context by using the following parameters:</p>
<p>&#8211;	skip.hadr.listener.pingcheck =&gt; Skip ping check of hadr listener<br />
&#8211;	skip.hadr.listener.tcpport   =&gt; Skip check of standard tcp port about  AG listerners<br />
&#8211;	skip.hadr.replica.tcpport    =&gt; Skip check of standard tcp port about AG replicas</p>
<p>For instance, in my context, I configured the <strong>hadr.replica.tcpport</strong> parameter to skip checks on replica ports because we own different environments that including several replicas on the same server and which listen on a non-default port.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Get-DbcConfig skip.hadr.*<br />
Name &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Value Description<br />
---- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ----- -----------<br />
skip.hadr.listener.pingcheck False Skip the HADR listener ping test (especially useful for Azure and AWS)<br />
skip.hadr.listener.tcpport &nbsp; False Skip the HADR AG Listener TCP port number (If port number is not standard acro...<br />
skip.hadr.replica.tcpport &nbsp; &nbsp; True Skip the HADR Replica TCP port number (If port number is not standard across t...</div></div>
<p>Running the HADR check can be simply run by using HADR tag as follows:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Invoke-DbcCheck -Tag HADR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
Pester v4.10.1 &nbsp;Executing all tests in 'C:\Program Files\WindowsPowerShell\Modules\dbachecks\1.2.29\checks\HADR.Tests.ps1' with Tags HADR &nbsp; <br />
...</div></div>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/04/161-2-hadr-checks-e1587413256656.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/04/161-2-hadr-checks-e1587413256656.jpg" alt="161 - 2 - hadr checks" width="1000" height="426" class="alignnone size-full wp-image-1599" /></a>                               </p>
<p>Well, this a good start but I think some almost of checks are state-oriented and some configuration checks are missing. I’m already willing to add some of them in a near the future or/and feel free to add your own contribution as well <img src="https://blog.developpez.com/mikedavem/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /> </p>
<p>Stay tuned! </p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Availability Group 2017 Direct seeding and updated default path policy</title>
		<link>https://blog.developpez.com/mikedavem/p13190/sql-server-2012/availability-group-2017-direct-seeding-and-updated-default-path-policy</link>
		<comments>https://blog.developpez.com/mikedavem/p13190/sql-server-2012/availability-group-2017-direct-seeding-and-updated-default-path-policy#comments</comments>
		<pubDate>Fri, 13 Mar 2020 18:10:10 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[SQL Server 2019]]></category>
		<category><![CDATA[AlwaysOn;groupes de disponibilité;availability groups]]></category>
		<category><![CDATA[direct seeding]]></category>
		<category><![CDATA[sqlserver]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1542</guid>
		<description><![CDATA[A couple of days ago, I ran into an issue when adding a new database in direct seeding mode that led me to reconsider refreshing my skills on this feature. Going through the AG database wizard for adding database, I &#8230; <a href="https://blog.developpez.com/mikedavem/p13190/sql-server-2012/availability-group-2017-direct-seeding-and-updated-default-path-policy">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A couple of days ago, I ran into an issue when adding a new database in direct seeding mode that led me to reconsider refreshing my skills on this feature. Going through the AG database wizard for adding database, I faced the following error message …</p>
<p><span id="more-1542"></span></p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/03/158-1-AG-wizard-failed.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/03/158-1-AG-wizard-failed.jpg" alt="158 - 1 - AG wizard failed" width="774" height="497" class="alignnone size-full wp-image-1543" /></a></p>
<p>… and I was surprised by the required directories value (L:\SQL\Data) because the correct topology should be:</p>
<p>&#8211;	D:\SQL\Data (SQL data files)<br />
&#8211;	L:\SQL\Logs (SQL Log files)</p>
<p>SQL Server 2016 required to have symmetric storage layout for both AG replicas but SQL Server 2017 and above seems to tell another story as specified to the <a href="https://docs.microsoft.com/en-us/sql/database-engine/availability-groups/windows/automatic-seeding-secondary-replicas?view=sql-server-ver15" rel="noopener" target="_blank">BOL</a>. In my context, I got the check script executed by the wizard and it became obvious that the direct seeding feature is checking if folders based on default path values exist on each replica.</p>
<p>In my context, I got the check script executed by the wizard and it became obvious that the direct seeding feature is checking if folders based on default path values exist on each replica.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;height:450px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">declare @SmoAuditLevel int<br />
&nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'AuditLevel', @SmoAuditLevel OUTPUT<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; declare @NumErrorLogs int<br />
&nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'NumErrorLogs', @NumErrorLogs OUTPUT<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; declare @SmoLoginMode int<br />
&nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', @SmoLoginMode OUTPUT<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; declare @ErrorLogSizeKb int<br />
&nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread &nbsp;N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'ErrorLogSizeInKb', @ErrorLogSizeKb OUTPUT<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; declare @SmoMailProfile nvarchar(512)<br />
&nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'MailAccountName', @SmoMailProfile OUTPUT<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; declare @BackupDirectory nvarchar(512)<br />
&nbsp; &nbsp; &nbsp; &nbsp; if 1=isnull(cast(SERVERPROPERTY('IsLocalDB') as bit), 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select @BackupDirectory=cast(SERVERPROPERTY('instancedefaultdatapath') as nvarchar(512))<br />
&nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @BackupDirectory OUTPUT<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; declare @SmoPerfMonMode int<br />
&nbsp; &nbsp; &nbsp; &nbsp; exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'Performance', @SmoPerfMonMode OUTPUT<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; if @SmoPerfMonMode is null<br />
&nbsp; &nbsp; &nbsp; &nbsp; begin <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; set @SmoPerfMonMode = 1000<br />
&nbsp; &nbsp; &nbsp; &nbsp; end<br />
&nbsp; &nbsp; &nbsp; <br />
<br />
SELECT<br />
@SmoAuditLevel AS [AuditLevel],<br />
ISNULL(@NumErrorLogs, -1) AS [NumberOfLogFiles],<br />
(case when @SmoLoginMode &amp;lt; 3 then @SmoLoginMode else 9 end) AS [LoginMode],<br />
ISNULL(SERVERPROPERTY(&amp;#039;instancedefaultdatapath&amp;#039;),&amp;#039;&amp;#039;) AS [DefaultFile],<br />
SERVERPROPERTY(&amp;#039;instancedefaultlogpath&amp;#039;) AS [DefaultLog],<br />
ISNULL(@ErrorLogSizeKb, 0) AS [ErrorLogSizeKb],<br />
-1 AS [TapeLoadWaitTime],<br />
ISNULL(@SmoMailProfile,N&amp;#039;&amp;#039;) AS [MailProfile],<br />
@BackupDirectory AS [BackupDirectory],<br />
@SmoPerfMonMode AS [PerfMonMode]</div></div>
<p><strong>Primary replica</strong></p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/03/158-3-AG-config-node-1-e1584122296250.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/03/158-3-AG-config-node-1-e1584122296250.jpg" alt="158 - 3 - AG config node 1" width="1000" height="69" class="alignnone size-full wp-image-1544" /></a></p>
<p><strong>Secondary replica</strong></p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/03/158-2-AG-config-node-2.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/03/158-2-AG-config-node-2.jpg" alt="158 - 2 - AG config node 2" width="964" height="82" class="alignnone size-full wp-image-1545" /></a></p>
<p>Even if directing seeding allows asymmetric storage layout, a mistake was introduced in my context and both replicas should have been aligned. It is therefore all the more important that using direct seeding capabilities from PowerShell cmdlets like <a href="https://docs.dbatools.io/#Restore-DbaDatabase" rel="noopener" target="_blank">Add-DbaAgDatabase</a> doesn&rsquo;t generate any errors and fixing the default path value for data and log require restarting the SQL Server instance. See you!</p>
<p>Hope this tips helps! </p>
<p>See you!</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Server service broker and curious duplicate messages case</title>
		<link>https://blog.developpez.com/mikedavem/p13185/sql-server-2008/sql-server-service-broker-and-curious-duplicate-messages</link>
		<comments>https://blog.developpez.com/mikedavem/p13185/sql-server-2008/sql-server-service-broker-and-curious-duplicate-messages#comments</comments>
		<pubDate>Sun, 22 Dec 2019 18:45:44 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[service broker]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1419</guid>
		<description><![CDATA[One of my last write-up to finish the year 2019. A couple of days ago, I ran into an interesting issue concerning a service broker architecture. Let’s introduce quickly the context: this is a start-based architecture with one target and &#8230; <a href="https://blog.developpez.com/mikedavem/p13185/sql-server-2008/sql-server-service-broker-and-curious-duplicate-messages">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>One of my last write-up to finish the year 2019. A couple of days ago, I ran into an interesting issue concerning a service broker architecture. Let’s introduce quickly the context: this is a start-based architecture with one target and more than 80 initiators as shown below:</p>
<p><span id="more-1419"></span></p>
<p><a href="http://blog.developpez.com/mikedavem/files/2019/12/152-0-SB-architecture.jpg"><img src="http://blog.developpez.com/mikedavem/files/2019/12/152-0-SB-architecture.jpg" alt="152 - 0 - SB architecture" width="494" height="574" class="alignnone size-full wp-image-1421" /></a></p>
<p>All messages are sent from the initiators to a single central target. Windows authentication for endpoint&rsquo;s connection and messages are encrypted before to be sent to the remote service by using certificates mapped to database users. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2019/12/152-1-SB-architecture.jpg"><img src="http://blog.developpez.com/mikedavem/files/2019/12/152-1-SB-architecture.jpg" alt="152 - 1 - SB architecture" width="838" height="486" class="alignnone size-full wp-image-1422" /></a></p>
<p>Installing such infrastructure is not trivial and during this year, we often had to deploy and reinitialize service broker configurations because we added new initiators, or some initiators were replaced by other ones. Therefore, on the DBA side we worked on an automatic way to interact with service broker configuration and it turns out that the natural way for us was to write a PowerShell module to address it. </p>
<p>A couple of days, for a sake of curiosity I implemented a service broker event based XE session and I noticed a bunch of broker_message_undeliverable messages with the reason: The message could not be delivered because it is a duplicate. See below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2019/12/152-2-xe-result.jpg"><img src="http://blog.developpez.com/mikedavem/files/2019/12/152-2-xe-result.jpg" alt="152 - 2 - xe result" width="1126" height="574" class="alignnone size-full wp-image-1424" /></a></p>
<p>What does it mean exactly? Well, according to my Google-fu and very-explained <a href="https://rusanu.com/2005/12/20/troubleshooting-dialogs/" rel="noopener" target="_blank">blog</a> from Remus Rusanu, it seems that the messages are accepted by the target, but the acks don’t reach back to the sender and therefore the sender is retrying the message again and again. But in my case, the sender ended up managing sending back the acknowledgement. </p>
<p>First step was to identify a misconfigured route between the target and the corresponding initiator. From broker instance value corresponds to the service broker id of the initiator. But surprisingly I didn’t find any misconfigured item. But I remembered the campaign of server rollout that had been going on for a few months where some servers were renamed following a new named convention. Furthermore, in our deployment process, dealing with new or renamed servers is exactly the same and we just initialize a new initiator and install a new route on the target regardless the scenario. But we forget one important point: because all routes are based on server name renaming a server leads to potentially to duplicate routes in this case. I verified my assumption by counting the number of existing routes on the target site:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT COUNT(*) FROM sys.routes</div></div>
<p>The result was 148 and we expect to get 85 routes in the current architecture confirming we have duplicate items here. Next step consisted in identifying and fixing duplicate routes:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2019/12/152-30-duplicate-routes-query.jpg"><img src="http://blog.developpez.com/mikedavem/files/2019/12/152-30-duplicate-routes-query.jpg" alt="152 - 30 - duplicate routes query" width="540" height="366" class="alignnone size-full wp-image-1430" /></a></p>
<p>Here a sample of duplicate routes I founded. The renaming server kept its service broker id and I easily identified duplicates by grouping by the broker instance.</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2019/12/152-3-duplicate-routes.jpg"><img src="http://blog.developpez.com/mikedavem/files/2019/12/152-3-duplicate-routes.jpg" alt="152 - 3 - duplicate routes" width="893" height="115" class="alignnone size-full wp-image-1425" /></a></p>
<p>After fixing the issue, messages related to duplicates disappear from the XE output.<br />
Hope this helps!</p>
<p>David Barbarin</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Recherche d&#8217;index et IO résiduels</title>
		<link>https://blog.developpez.com/mikedavem/p13173/sql-server-2012/recherche-dindex-et-io-residuels</link>
		<comments>https://blog.developpez.com/mikedavem/p13173/sql-server-2012/recherche-dindex-et-io-residuels#comments</comments>
		<pubDate>Mon, 12 Feb 2018 17:57:10 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[SQL Server 2017]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1390</guid>
		<description><![CDATA[Ce billet fait suite au précédent à propos des recherches d&#8217;index et les pièges associés. J&#8217;ai pu rencontrer un autre cas intéressant mais ce n&#8217;est pas tellement la nature du problème qui m&#8217;a décidé à écrire mais plutôt les différentes &#8230; <a href="https://blog.developpez.com/mikedavem/p13173/sql-server-2012/recherche-dindex-et-io-residuels">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Ce billet fait suite au <a href="https://blog.dbi-services.com/when-index-seek-operation-is-not-always-your-friend/" rel="noopener" target="_blank">précédent</a> à propos des recherches d&rsquo;index et les pièges associés. J&rsquo;ai pu rencontrer un autre cas intéressant mais ce n&rsquo;est pas tellement la nature du problème qui m&rsquo;a décidé à écrire mais plutôt les différentes façons qu&rsquo;il existe de l&rsquo;appréhender.</p>
<p>&gt; <a href="https://blog.dbi-services.com/index-seek-operator-and-residual-io/" rel="noopener" target="_blank">Lire la suite</a> (en anglais)</p>
<p>David Barbarin<br />
MVP &amp; MCM SQL Server</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Déplacer des tables en ligne vers des groupes de fichiers avec contraintes et LOB</title>
		<link>https://blog.developpez.com/mikedavem/p13168/sql-server-2008/deplacer-des-tables-en-ligne-vers-des-groupes-de-fichiers-avec-contraintes-et-lob</link>
		<comments>https://blog.developpez.com/mikedavem/p13168/sql-server-2008/deplacer-des-tables-en-ligne-vers-des-groupes-de-fichiers-avec-contraintes-et-lob#comments</comments>
		<pubDate>Thu, 25 Jan 2018 07:01:00 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[Administration]]></category>
		<category><![CDATA[groupe de fichiers]]></category>
		<category><![CDATA[LOB]]></category>
		<category><![CDATA[Migration]]></category>
		<category><![CDATA[partition]]></category>
		<category><![CDATA[partitioning]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1378</guid>
		<description><![CDATA[Commençons cette semaine en revenant sur une discussion intéressante que j&#8217;ai eu avec un de mes clients pour déplacer plusieurs tables vers différents groupes de fichiers. Certaines d&#8217;entre elles contenaient des données LOB. Ajoutons à cela une contrainte supplémentaire du &#8230; <a href="https://blog.developpez.com/mikedavem/p13168/sql-server-2008/deplacer-des-tables-en-ligne-vers-des-groupes-de-fichiers-avec-contraintes-et-lob">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Commençons cette semaine en revenant sur une discussion intéressante que j&rsquo;ai eu avec un de mes clients pour déplacer plusieurs tables vers différents groupes de fichiers. Certaines d&rsquo;entre elles contenaient des données LOB. Ajoutons à cela une contrainte supplémentaire du client: déplacer tout ce petit monde en ligne pour éviter d&rsquo;impacter la disponibilité des données durant le processus de migration. Les tables concernées possèdaient des contraintes de schéma comme une clé primaire et des clés étrangères ainsi que des index non cluster. Finalement quelque chose de plutôt classique avec lequel nous pouvons avoir à faire tous les jours chez les clients.</p>
<p>&gt; <a href="https://blog.dbi-services.com/moving-tables-online-on-filegroup-with-constraints-and-lob-data/" rel="noopener" target="_blank">Lire la suite</a> (en anglais)</p>
<p>David Barbarin<br />
MVP &amp; MCM SQL Server</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Saturday Toulouse 2017: SQL Server sur Linux – les slides</title>
		<link>https://blog.developpez.com/mikedavem/p13166/sql-server-2012/sql-saturday-toulouse-2017-sql-server-sur-linux-les-slides</link>
		<comments>https://blog.developpez.com/mikedavem/p13166/sql-server-2012/sql-saturday-toulouse-2017-sql-server-sur-linux-les-slides#comments</comments>
		<pubDate>Tue, 02 Jan 2018 19:10:38 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[SQLSaturday]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1370</guid>
		<description><![CDATA[#SQLSatToulouse a été un bon cru. Premierèment, je voudrais remercier chaleureusement l&#8217;équipe organisatrice (@Guss et @Fredg_31) ainsi que les sponsors et participants (sans qui ce qui ce genre d&#8217;événement ne serait pas possible). Comme promis, vous trouverez les slides de &#8230; <a href="https://blog.developpez.com/mikedavem/p13166/sql-server-2012/sql-saturday-toulouse-2017-sql-server-sur-linux-les-slides">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>#SQLSatToulouse a été un bon cru. Premierèment, je voudrais remercier chaleureusement l&rsquo;équipe organisatrice (<a href="https://twitter.com/GUSS_FRANCE" rel="noopener" target="_blank">@Guss</a> et <a href="https://twitter.com/31_fredg" rel="noopener" target="_blank">@Fredg_31</a>) ainsi que les sponsors et participants (sans qui ce qui ce genre d&rsquo;événement ne serait pas possible).</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2018/01/blog-124-sqlonlinuxsqlsattoulouse-e1505723769237.jpg"><img src="http://blog.developpez.com/mikedavem/files/2018/01/blog-124-sqlonlinuxsqlsattoulouse-e1505723769237.jpg" alt="blog-124-sqlonlinuxsqlsattoulouse-e1505723769237" width="800" height="450" class="alignnone size-full wp-image-1371" /></a></p>
<p>Comme promis, vous trouverez les slides de ma session &laquo;&nbsp;<a href="https://1drv.ms/b/s!AsVfOWRG1E9ig9BXJjLNKQK3kaV6YQ" rel="noopener" target="_blank">Introduction to SQL Server on Linux for DBAs</a>&laquo;&nbsp;. Définitivement un bon moment de partage.</p>
<p>Merci à tous!</p>
<p>David Barbarin<br />
MVP &amp; MCM SQL Server</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Première installation de SQL Server sur Linux Red Hat 7.2</title>
		<link>https://blog.developpez.com/mikedavem/p13133/sql-server-2012/premiere-installation-de-sql-server-sur-linux-red-hat-7-2</link>
		<comments>https://blog.developpez.com/mikedavem/p13133/sql-server-2012/premiere-installation-de-sql-server-sur-linux-red-hat-7-2#comments</comments>
		<pubDate>Sun, 15 Jan 2017 15:56:05 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Red Hat]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1300</guid>
		<description><![CDATA[Les premières annonces de Microsoft sur la sortie d&#8217;une version sous Linux sont prometteuses. Bien entendu nous sommes loin d&#8217;une version finale et la liste des fonctionnalités non supportées sera probablement un bon indicateur de la maturité du produit avec &#8230; <a href="https://blog.developpez.com/mikedavem/p13133/sql-server-2012/premiere-installation-de-sql-server-sur-linux-red-hat-7-2">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Les premières annonces de Microsoft sur la sortie d&rsquo;une version sous Linux sont prometteuses. Bien entendu nous sommes loin d&rsquo;une version finale et la liste des fonctionnalités non supportées sera probablement un bon indicateur de la maturité du produit avec le temps. Comme beaucoup de gens je suppose, je n&rsquo;ai pas attendu longtemps pour tenter une première installation sur Linux. Le processus d&rsquo;installation semble bien documenté et ca sera l&rsquo;occasion de partager mes premières impressions.</p>
<p>&gt; <a href="http://blog.dbi-services.com/first-installation-of-sql-server-on-linux-rehl-7-2/" target="_blank">Lire la suite</a> (en anglais)</p>
<p>David Barbarin<br />
MVP &amp; MCM SQL Server</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
