<?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; sqlserver</title>
	<atom:link href="https://blog.developpez.com/mikedavem/ptag/sqlserver/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>Extending SQL Server monitoring with Raspberry PI and Lametric</title>
		<link>https://blog.developpez.com/mikedavem/p13204/sql-server-2005/extending-sql-server-monitoring-with-raspberry-pi-and-lametric</link>
		<comments>https://blog.developpez.com/mikedavem/p13204/sql-server-2005/extending-sql-server-monitoring-with-raspberry-pi-and-lametric#comments</comments>
		<pubDate>Thu, 07 Jan 2021 21:59:25 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[K8s]]></category>
		<category><![CDATA[SQL Azure]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2008 R2]]></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[Lametric]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Raspberry]]></category>
		<category><![CDATA[sqlserver]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1742</guid>
		<description><![CDATA[First blog of this new year 2021 and I will start with a fancy and How-To Geek topic In my last blog post, I discussed about monitoring and how it should help to address quickly a situation that is going &#8230; <a href="https://blog.developpez.com/mikedavem/p13204/sql-server-2005/extending-sql-server-monitoring-with-raspberry-pi-and-lametric">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>First blog of this new year 2021 and I will start with a fancy and How-To Geek topic </p>
<p>In my <a href="https://blog.developpez.com/mikedavem/p13203/sql-server-2014/why-we-moved-sql-server-monitoring-on-prometheus-and-grafana" rel="noopener" target="_blank">last blog post</a>, I discussed about monitoring and how it should help to address quickly a situation that is going degrading. Alerts are probably the first way to raise your attention and, in my case, they are often in the form of emails in a dedicated folder. That remains a good thing, at least if you’re not focusing too long in other daily tasks or projects. In work office, I know I would probably better focus on new alerts but as I said previously, telework changed definitely the game.  </p>
<p><span id="more-1742"></span></p>
<p>I wanted to find a way to address this concern at least for main SQL Server critical alerts and I thought about relying on my existing home lab infrastructure to address the point. Reasons are it is always a good opportunity to learn something and to improve my skills by referring to a real case scenario. </p>
<p>My home lab infrastructure includes a cluster of <a href="https://www.raspberrypi.org/products/raspberry-pi-4-model-b/" rel="noopener" target="_blank">Raspberry PI 4</a> nodes. Initially, I use it to improve my skills on K8s or to study some IOT stuff for instance. It is a good candidate for developing and deploying a new app for detecting new incoming alerts in my mailbox and sending notifications to my Lametric accordingly. </p>
<p><a href="https://lametric.com/" rel="noopener" target="_blank">Lametric</a> is a basically a connected clock but works also as a highly-visible display showing notifications from devices or apps via REST APIs. First time I saw such device in action was in a DevOps meetup in 2018 around Docker and Jenkins deployment with <a href="https://www.linkedin.com/in/duquesnoyeric/" rel="noopener" target="_blank">Eric Dusquenoy</a> and Tim Izzo (<a href="https://twitter.com/5ika_" rel="noopener" target="_blank">@5ika_</a>). In addition, one of my previous customers had also one in his office and we had some discussions about cool customization through Lametric apps. </p>
<p>Connection through VPN to my company network is mandatory to work from home and unfortunately Lametric device doesn’t support this scenario because communication is limited to local network only. So, I need an app that run on my local (home) network and able to connect to my mailbox, get new incoming emails and finally sending notifications to my Lametric device. </p>
<p>Here my setup:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/01/171-0-lametric_infra.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/01/171-0-lametric_infra-1024x711.jpg" alt="171 - 0 - lametric_infra" width="584" height="405" class="alignnone size-large wp-image-1743" /></a></p>
<p>There are plenty of good blog posts to create a Raspberry cluster on the internet and I would suggest to read <a href="https://dbafromthecold.com/2020/11/30/building-a-raspberry-pi-cluster-to-run-azure-sql-edge-on-kubernetes/" rel="noopener" target="_blank">that</a> of Andrew Pruski (<a href="https://twitter.com/dbafromthecold" rel="noopener" target="_blank">@dbafromthecold</a>). </p>
<p>As shown above, there are different paths for SQL alerts referring our infrastructure (On-prem and Azure SQL databases) but all of them are send to a dedicated distribution list for DBA. </p>
<p>The app is a simple PowerShell script that relies on Exchange Webservices APIs for connecting to the mailbox and to get new mails. Sending notifications to my Lametric device is achieved by a simple REST API call with well-formatted body. Details can be found the <a href="https://lametric-documentation.readthedocs.io/en/latest/reference-docs/device-notifications.html" rel="noopener" target="_blank">Lametric documentation</a>. As prerequisite, you need to create a notification app from Lametric Developer site as follows:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/01/171-3-lametric-app-token.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/01/171-3-lametric-app-token-1024x364.jpg" alt="171 - 3 - lametric app token" width="584" height="208" class="alignnone size-large wp-image-1744" /></a></p>
<p>As said previously, I used PowerShell for this app. It can help to find documentation and tutorials when it comes Microsoft product. But if you are more confident with Python, APIs are also available in a <a href="https://pypi.org/project/py-ews/" rel="noopener" target="_blank">dedicated package</a>. But let’s precise that using PowerShell doesn’t necessarily mean using Windows-based container and instead I relied on Linux-based image with PowerShell core for ARM architecture. Image is provided by Microsoft on <a href="https://hub.docker.com/_/microsoft-powershell" rel="noopener" target="_blank">Docker Hub</a>. Finally, sensitive information like Lametric Token or mailbox credentials are stored in K8s secret for security reasons. My app project is available on my <a href="https://github.com/mikedavem/lametric" rel="noopener" target="_blank">GitHub</a>. Feel free to use it.</p>
<p>Here some results:</p>
<p>&#8211; After deploying my pod:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/01/171-1-lametric-pod.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/01/171-1-lametric-pod.jpg" alt="171 - 1 - lametric pod" width="483" height="82" class="alignnone size-full wp-image-1745" /></a></p>
<p>&#8211; The app is running and checking new incoming emails (kubectl logs command)</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/01/171-2-lametric-pod-logs.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/01/171-2-lametric-pod-logs.jpg" alt="171 - 2 - lametric pod logs" width="828" height="438" class="alignnone size-full wp-image-1747" /></a></p>
<p>When email is detected, <a href="https://youtu.be/EcdSFziNc3U" title="Notification" rel="noopener" target="_blank">notification</a> is sendig to Lametric device accordingly</p>
<p>Geek fun good (bad?) idea to start this new year 2021 <img src="https://blog.developpez.com/mikedavem/wp-includes/images/smilies/icon_smile.gif" alt=":-)" class="wp-smiley" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why we moved SQL Server monitoring on Prometheus and Grafana</title>
		<link>https://blog.developpez.com/mikedavem/p13203/sql-server-2014/why-we-moved-sql-server-monitoring-on-prometheus-and-grafana</link>
		<comments>https://blog.developpez.com/mikedavem/p13203/sql-server-2014/why-we-moved-sql-server-monitoring-on-prometheus-and-grafana#comments</comments>
		<pubDate>Tue, 22 Dec 2020 16:55:12 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Performance]]></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[Continuous Delivery]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[grafana]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[observability]]></category>
		<category><![CDATA[prometheus]]></category>
		<category><![CDATA[RED]]></category>
		<category><![CDATA[sqlserver]]></category>
		<category><![CDATA[telegraf]]></category>
		<category><![CDATA[USE]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1722</guid>
		<description><![CDATA[During this year, I spent a part of my job on understanding the processes and concepts around monitoring in my company. The DevOps mindset mainly drove the idea to move our SQL Server monitoring to the existing Prometheus and Grafana &#8230; <a href="https://blog.developpez.com/mikedavem/p13203/sql-server-2014/why-we-moved-sql-server-monitoring-on-prometheus-and-grafana">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>During this year, I spent a part of my job on understanding the processes and concepts around monitoring in my company. The DevOps mindset mainly drove the idea to move our SQL Server monitoring to the existing Prometheus and Grafana infrastructure. Obviously, there were some technical decisions behind the scene, but the most important part of this write-up is dedicated to explaining other and likely most important reasons of this decision. </p>
<p><span id="more-1722"></span></p>
<p>But let’s precise first, this write-up doesn’t constitute any guidance or any kind of best practices for DBAs but only some sharing of my own experience on the topic. As usual, any comment will be appreciated.</p>
<p>That’s said, let’s continue with the context. At the beginning of this year, I started my new DBA position in a customer-centric company where DevOps culture, microservices and CI/CD are omnipresent. What does it mean exactly? To cut the story short, development and operation teams are used a common approach for agile software development and delivery. Tools and processes are used to automate build, test, deploy and to monitor applications with speed, quality and control. In other words, we are talking about Continuous Delivery and in my company, release cycle is faster than traditional shops I encountered so far with several releases per day including database changes. Another interesting point is that we are following the &laquo;&nbsp;Operate what you build&nbsp;&raquo; principle each team that develops a service is also responsible for operating and supporting it. It presents some advantages for both developers and operations but pushing out changes requires to get feedback and to observe impact on the system on both sides. </p>
<p>In addition, in operation teams we try to act as a centralized team and each member should understand the global scope and topics related to the infrastructure and its ecosystem. This is especially true when you&rsquo;re dealing with nightly on-calls. Each has its own segment responsibility (regarding their specialized areas) but following DevOps principles, we encourage shared ownership to break down internal silos for optimizing feedback and learning. It implies anyone should be able to temporarily overtake any operational task to some extent assuming the process is well-documented, and learnin has been done correctly. But world is not perfect and this model has its downsides. For example, it will prioritize effectiveness in broader domains leading to increase cognitive load of each team member and to lower visibility in for vertical topics when deeper expertise is sometimes required. Having an end-to-end observable system including infrastructure layer and databases may help to reduce time for investigating and fixing issues before end users experience them. </p>
<p><strong>The initial scenario</strong></p>
<p>Let me give some background info and illustration of the initial scenario:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-0-initial-scenario.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-0-initial-scenario-1024x704.jpg" alt="170 - 0 - initial scenario" width="584" height="402" class="alignnone size-large wp-image-1725" /></a></p>
<p>… and my feeling of what could be improved:</p>
<p>1) From a DBA perspective, at a first glance there are many potential issues. Indeed, a lot of automated or semi-manual deployment processes are out of the control and may have a direct impact on the database environment stability. Without better visibility, there is likely no easy way to address the famous question: He, we are experiencing performance degradations for two days, has something happened on database side?  </p>
<p>2) Silos are encouraged between DBA and DEVs in this scenario. Direct consequence is to limit drastically the adding value of the DBA role in a DevOps context. Obviously, primary concerns include production tasks like ensuring integrity, backups and maintenance of databases. But in a DevOps oriented company where we have automated &laquo;&nbsp;database-as-code&nbsp;&raquo; pipelines, they remain lots of unnecessary complexity and disruptive scripts that DBA should take care. If this role is placed only at the end of the delivery pipeline, collaboration and continuous learning with developer teams will restricted at minimum.  </p>
<p>3) There is a dedicated monitoring tool for SQL Server infrastructure and this is a good point. It provides necessary baselining and performance insights for DBAs. But in other hand, the tool in place targets only DBA profiles and its usage is limited to the infrastructure team. This doesn’t contribute to help improving the scalability in the operations team and beyond. Another issue with the existing tooling is correlation can be difficult with external events that come from either the continuous delivery pipeline or configuration changes performed by operations teams on the SQL Server instances. In this case, establishment of observability (the why) may be limited and this is what teams need to respond quickly and resolve emergencies in modern and distributed software.</p>
<p><strong>What is observability?</strong></p>
<p>You probably noticed the word &laquo;&nbsp;observability&nbsp;&raquo; in my previous sentence, so I think it deserves some explanations before to continue. Observability might seem like a buzzword but in fact it is not a new concept but became prominent in DevOps software development lifecycle (SDLC) methodologies and distributed infrastructure systems. Referring to the <a href="Implementing new monitoring stuff changed the way to observe the system (at least from a DBA perspective). Again, I believe the adding value of DBA role in a company with a strong DevOps mindset is being part of both production DBAs and Development DBAs. Making observability consistent across all the delivery pipeline including databases is likely part of the success and may help DBA getting a broader picture of system components. Referring to my context, I’m now able to get more interaction with developer teams on early phases and to provide them contextual feedbacks (and not generic feedbacks) for improvements regarding SQL production telemetry. They also have access to them and can check by themselves impact of their development.  In the same way, feedbacks and work with my team around database infrastructure topic may appear more relevant. It is finally a matter of collaboration " rel="noopener" target="_blank">Wikipedia</a> definition, <strong>Observability is the ability to infer internal states of a system based on the system’s external outputs</strong>. To be honest, it has not helped me very much and further readings were necessary to shed the light on what observability exactly is and what difference exist with monitoring. </p>
<p>Let’s start instead with monitoring which is the ability to translate infrastructure log metrics data into meaningful and actionable insights. It helps knowing when something goes wrong and starting your response quickly. This is the basis for monitoring tool and the existing one is doing a good job on it. In DBA world, monitoring is often related to performance but reporting performance is only as useful as that reporting accurately represents the internal state of the global system and not only your database environment. For example, in the past I went to some customer shops where I was in charge to audit their SQL Server infrastructure. Generally, customers were able to present their context, but they didn’t get the possibility to provide real facts or performance metrics of their application. In this case, you usually rely on a top-down approach and if you’re either lucky or experimented enough, you manage to find what is going wrong. But sometimes I got relevant SQL Server metrics that would have highlighted a database performance issue, but we didn’t make a clear correlation with those identified on application side. In this case, relying only on database performance metrics was not enough for inferring the internal state of the application. From my experience, many shops are concerned with such applications that have been designed for success and not for failure. They often lake of debuggability monitoring and telemetry is often missing. Collecting data is as the base of observability.</p>
<p>Observability provides not only the when of an error or issue, but more importantly the why. With modern software architectures including micro-services and the emphasis of DevOps, monitoring goals are no longer limited to collecting and processing log data, metrics, and event traces. Instead, it should be employed to improve observability by getting a better understanding of the properties of an application and its performance across distributed systems and delivery pipeline. Referring to the new context I&rsquo;m working now, metric capture and analysis is started with deployment of each micro-service and it provides better observability by measuring all the work done across all dependencies.</p>
<p><strong>White-Box vs. Black-Box Monitoring </strong></p>
<p>In my company as many other companies, different approaches are used when it comes monitoring: White-box and Black-Box monitoring.<br />
White-box monitoring focuses on exposing internals of a system. For example, this approach is used by many SQL Server performance tools on the market that make effort to set a map of the system with a bunch of internal statistic data about index or internal cache usage, existing wait stats, locks and so on …</p>
<p>In contrast, black-Box monitoring is symptom oriented and tests externally visible behavior as a user would see it. Goal is only monitoring the system from the outside and seeing ongoing problems in the system. There are many ways to achieve black-box monitoring and the first obvious one is using probes which will collect CPU or memory usage, network communications, HTTP health check or latency and so on … Another option is to use a set of integration tests that run all the time to test the system from a behavior / business perspective.</p>
<p>White-Box vs. Black-Box Monitoring: Which is finally more important? All are and can work together. In my company, both are used at different layers of the micro-service architecture including software and infrastructure components. </p>
<p><strong>RED vs USE monitoring</strong></p>
<p>When you’re working in a web-oriented and customer-centric company, you are quickly introduced to The Four Golden Signals monitoring concept which defines a series of metrics originally from <a href="https://sre.google/sre-book/monitoring-distributed-systems/" rel="noopener" target="_blank">Google Site Reliability Engineering</a> including latency, traffic, errors and saturation. The RED method is a subset of “Four Golden Signals” and focus on micro-service architectures and include following metrics:</p>
<ul>
<li>Rate: number of requests our service is serving per second</li>
<li>Error: number of failed requests per second </li>
<li>Duration: amount of time it takes to process a request</li>
</ul>
<p>Those metrics are relatively straightforward to understand and may reduce time to figure out which service was throwing the errors and then eventually look at the logs or to restart the service, whatever. </p>
<p>For HTTP Metrics the RED Method is a good fit while the USE Method is more suitable for infrastructure side where main concern is to keep physical resources under control. The latter is based on 3 metrics:</p>
<ul>
<li>Utilization: Mainly represented in percentage and indicates if a resource is in underload or overload state. </li>
<li>Saturation: Work in a queue and waiting to be processed</li>
<li>Errors: Count of event errors</li>
</ul>
<p>Those metrics are commonly used by DBAs to monitor performance. It is worth noting that utilization metric can be sometimes misinterpreted especially when maximum value depends of the context and can go over 100%. </p>
<p><strong>SQL Server infrastructure monitoring expectations</strong></p>
<p>Referring to the starting scenario and all concepts surfaced above, it was clear for us to evolve our existing SQL Server monitoring architecture to improve our ability to reach the following goals:</p>
<ul>
<li>Keeping analyzing long-term trends to respond usual questions like how my daily-workload is evolving? How big is my database? …</li>
<li>Alerting to respond for a broken issue we need to fix or for an issue that is going on and we must check soon.</li>
<li>Building comprehensive dashboards – dashboards should answer basic questions about our SQL Server instances, and should include some form of the advanced SQL telemetry and logging for deeper analysis.</li>
<li>Conducting an ad-hoc retrospective analysis with easier correlation: from example an http response latency that increased in one service. What happened around? Is-it related to database issue? Or blocking issue raised on the SQL Server instance? Is it related to a new query or schema change deployed from the automated delivery pipeline? In other words, good observability should be part of the new solution.</li>
<li>Automated discovery and telemetry collection for every SQL Server instance installed on our environment, either on VM or in container.</li>
<li>To rely entirely on the common platform monitoring based on Prometheus and Grafana. Having the same tooling make often communication easier between people (human factor is also an important aspect of DevOps) </li>
</ul>
<p><strong>Prometheus, Grafana and Telegraf</strong></p>
<p>Prometheus and Grafana are the central monitoring solution for our micro-service architecture. Some others exist but we’ll focus on these tools in the context of this write-up.<br />
Prometheus is an open-source ecosystem for monitoring and alerting. It uses a multi-dimensional data model based on time series data identified by metric name and key/value pairs. WQL is the query language used by Prometheus to aggregate data in real time and data are directly shown or consumed via HTTP API to allow external system like Grafana. Unlike previous tooling, we appreciated collecting SQL Server metrics as well as those of the underlying infrastructure like VMWare and others. It allows to comprehensive picture of a full path between the database services and infrastructure components they rely on. </p>
<p>Grafana is an open source software used to display time series analytics. It allows us to query, visualize and generate alerts from our metrics. It is also possible to integrate a variety of data sources in addition of Prometheus increasing the correlation and aggregation capabilities of metrics from different sources. Finally, Grafana comes with a native annotation store and the ability to add annotation events directly from the graph panel or via the HTTP API. This feature is especially useful to store annotations and tags related to external events and we decided to use it for tracking software releases or SQL Server configuration changes. Having such event directly on dashboard may reduce troubleshooting effort by responding faster to the why of an issue.  </p>
<p>For collecting data we use <a href="https://github.com/influxdata/telegraf/tree/master/plugins/inputs/sqlserver" rel="noopener" target="_blank">Telegraf plugin</a> for SQL Server. The plugin exposes all configured metrics to be polled by a Prometheus server. The plugin can be used for both on-prem and Azure instances including Azure SQL DB and Azure SQL MI. Automated deployment and configuration requires low effort as well. </p>
<p>The high-level overview of the new implemented monitoring solution is as follows:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-3-monitoring-architecture.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-3-monitoring-architecture-1024x776.jpg" alt="170 - 3 - monitoring architecture" width="584" height="443" class="alignnone size-large wp-image-1729" /></a></p>
<p>SQL Server telemetry is achieved through Telegraf + Prometheus and includes both Black-box and White-box oriented metrics. External events like automated deployment, server-level and database-level configuration changes are monitored through a centralized scheduled framework based on PowerShell. Then annotations + tags are written accordingly to Grafana and event details are recorded to logging tables for further troubleshooting.</p>
<p><strong>Did the new monitoring met our expectations?</strong></p>
<p>Well, having experienced the new monitoring solution during this year, I would say we are on a good track. We worked mainly on 2 dashboards. The first one exposes basic black-box metrics to show quickly if something is going wrong while the second one is DBA oriented with a plenty of internal counters to dig further and to perform retrospective analysis.</p>
<p>Here a sample of representative issues we faced this year and we managed to fix with the new monitoring solution:</p>
<p>1) Resource pressure and black-box monitoring in action:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-4-grafana-1.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-4-grafana-1-1024x168.jpg" alt="170 - 4 - grafana 1" width="584" height="96" class="alignnone size-large wp-image-1730" /></a></p>
<p>For this scenario, the first dashboard highlighted resource pressure issues, but it is worth noting that even if the infrastructure was burning, users didn’t experience any side effects or slowness on application side. After corresponding alerts raised on our side, we applied proactive and temporary fixes before users experience them. I would say, this scenario is something we would able to manage with previous monitoring and the good news is we didn’t notice any regression on this topic. </p>
<p>2) Better observability for better resolution of complex issue</p>
<p>This scenario was more interesting because the first symptom started from the application side without alerting the infrastructure layer. We started suffering from HTTP request slowness on November around 12:00am and developers got alerted with sporadic timeout issues from the logging system. After they traversed the service graph, they spotted on something went wrong on the database service by correlating http slowness with blocked processes on SQL Server dashboard as shown below. I put a simplified view on the dashboards, but we need to cross several routes between the front-end services and databases.</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-6-grafana-3.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-6-grafana-3-1024x235.jpg" alt="170 - 6 - grafana 3" width="584" height="134" class="alignnone size-large wp-image-1732" /></a></p>
<p>Then I got a call from them and we started investigating blocking processes from the logging tables in place on SQL Server side. At a first glance, different queries with a longer execution time than usual and neither release deployments nor configuration updates may explain such sudden behavior change. The issue kept around and at 15:42 it started appearing more frequently to deserve a deeper look at the SQL Server internal metrics. We quickly found out some interesting correlation with other metrics and we finally managed to figure out why things went wrong as show below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-7-grafana-4.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-7-grafana-4-706x1024.jpg" alt="170 - 7 - grafana 4" width="584" height="847" class="alignnone size-large wp-image-1733" /></a></p>
<p>Root cause was related to transaction replication slowness within Always On availability group databases and we directly jumped on storage issue according to error log details on secondary: </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-8-errorlog.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-8-errorlog-1024x206.jpg" alt="170 - 8 - errorlog" width="584" height="117" class="alignnone size-large wp-image-1734" /></a></p>
<p>End-to-End observability by including the database services to the new monitoring system drastically reduces the time for finding the root cause. But we also learnt from this experience and to continuously improve the observability we added a black-box oriented metric related to availability group replication latency (see below) to detect faster any potential issue.</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-9-avg-replication-metric.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-9-avg-replication-metric.jpg" alt="170 - 9 - avg replication metric" width="160" height="113" class="alignnone size-full wp-image-1736" /></a></p>
<p><strong>And what’s next? </strong></p>
<p>Having such monitoring is not the endpoint of this story. As said at the beginning of this write-up, continuous delivery comes with its own DBA challenges illustrated by the starting scenario. Traditionally the DBA role is siloed, turning requests or tickets into work and they can be lacking context about the broader business or technology used in the company. I experienced myself several situations where you get alerted during the night when developer’s query exceeds some usage threshold. Having discussed the point with many DBAs, they tend to be conservative about database changes (normal reaction?) especially when you are at the end of the delivery process without clear view of what will could deployed exactly. </p>
<p>Here the new situation:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/12/170-2-new-scenario.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/12/170-2-new-scenario-1024x641.jpg" alt="170 - 2 - new scenario" width="584" height="366" class="alignnone size-large wp-image-1737" /></a></p>
<p>Implementing new monitoring stuff changed the way to observe the system (at least from a DBA perspective). Again, I believe the adding value of DBA role in a company with a strong DevOps mindset is being part of both production DBAs and Development DBAs. Making observability consistent across all the delivery pipeline including databases is likely part of the success and may help DBA getting a broader picture of system components. Referring to my context, I’m now able to get more interaction with developer teams on early phases and to provide them contextual feedbacks (and not generic feedbacks) for improvements regarding SQL production telemetry. They also have access to them and can check by themselves impact of their development.  In the same way, feedbacks and work with my team around database infrastructure topic may appear more relevant. </p>
<p>It is finally a matter of collaboration </p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>5</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>Universal usage of NVARCHAR type and performance impact</title>
		<link>https://blog.developpez.com/mikedavem/p13195/sql-server-vnext/universal-usage-of-nvarchar-type-and-performance-impact</link>
		<comments>https://blog.developpez.com/mikedavem/p13195/sql-server-vnext/universal-usage-of-nvarchar-type-and-performance-impact#comments</comments>
		<pubDate>Wed, 27 May 2020 17:06:24 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[convert_implicit]]></category>
		<category><![CDATA[nvarchar]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Query Store]]></category>
		<category><![CDATA[sqlserver]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1604</guid>
		<description><![CDATA[A couple of weeks, I read an article from Brent Ozar about using NVARCHAR as a universal parameter. It was a good reminder and from my experience, I confirm this habit has never been a good idea. Although it depends &#8230; <a href="https://blog.developpez.com/mikedavem/p13195/sql-server-vnext/universal-usage-of-nvarchar-type-and-performance-impact">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A couple of weeks, I read an <a href="https://www.brentozar.com/archive/2020/04/can-you-use-nvarchar-as-a-universal-parameter-almost/" rel="noopener" target="_blank">article</a> from Brent Ozar about using NVARCHAR as a universal parameter. It was a good reminder and from my experience, I confirm this habit has never been a good idea. Although it depends on the context, chances are you will almost find an exception that proves the rule. </p>
<p><span id="more-1604"></span></p>
<p>A couple of days ago, I felt into a situation that illustrated perfectly this issue, and, in this blog, I decided to share my experience and demonstrate how the impact may be in a real production scenario.<br />
So, let’s start with the culprit. I voluntary masked some contextual information but the principal is here. The query is pretty simple:</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">DECLARE @P0 DATETIME <br />
DECLARE @P1 INT<br />
DECLARE @P2 NVARCHAR(4000) <br />
DECLARE @P3 DATETIME <br />
DECLARE @P4 NVARCHAR(4000)<br />
<br />
UPDATE TABLE SET DATE = @P0<br />
WHERE ID = @P1<br />
&nbsp;AND IDENTIFIER = @P2<br />
&nbsp;AND P_DATE &amp;gt;= @P3<br />
&nbsp;AND W_O_ID = (<br />
&nbsp; &nbsp;SELECT TOP 1 ID FROM TABLE2<br />
&nbsp; &nbsp;WHERE Identifier = @P4<br />
&nbsp; &nbsp;ORDER BY ID DESC)</div></div>
<p>And the corresponding execution plan: </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-1-excution_plan_with_implicit_conversion-e1590596511773.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-1-excution_plan_with_implicit_conversion-e1590596511773.jpg" alt="162 - 1 - excution_plan_with_implicit_conversion" width="1000" height="380" class="alignnone size-full wp-image-1605" /></a></p>
<p>The most interesting part concerns the TABLE2 table. As you may notice the @P4 input parameter type is NVARCHAR and it is evident we get a CONVERT_IMPLICIT in the concerned Predicate section above. The CONVERT_IMPLICIT function is required because of <a href="https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-ver15" rel="noopener" target="_blank">data type precedence</a>. It results to a costly operator that will scan all the data from TABLE2. As you probably know, CONVERT_IMPLICT prevents sargable condition and normally this is something we could expect here referring to the distribution value in the statistic histogram and the underlying index on the Identifier column.</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">EXEC sp_helpindex 'TABLE2';</div></div>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-8-index-config.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-8-index-config.jpg" alt="162 - 8 - index config" width="1035" height="135" class="alignnone size-full wp-image-1606" /></a></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">DBCC SHOW_STATISTICS ('TABLE2', 'IX___IDENTIFIER')<br />
WITH HISTOGRAM;</div></div>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-10-histogram-stats.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-10-histogram-stats.jpg" alt="162 - 10 - histogram stats" width="877" height="435" class="alignnone size-full wp-image-1620" /></a></p>
<p>Another important point to keep in mind is that scanning all the data from the TABLE 2 table may be at a certain cost (&gt; 1GB) even if data resides in memory.</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">EXEC sp_spaceused 'TABLE2'</div></div>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-9-index-space-used.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-9-index-space-used.jpg" alt="162 - 9 - index space used" width="725" height="62" class="alignnone size-full wp-image-1607" /></a></p>
<p>The execution plan warning confirms the potential overhead of retrieving few rows in the TABLE2 table:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-2-excution_plan_with_implicit_conversion-arning.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-2-excution_plan_with_implicit_conversion-arning.jpg" alt="162 - 2 - excution_plan_with_implicit_conversion arning" width="1160" height="108" class="alignnone size-full wp-image-1608" /></a></p>
<p>To set a little bit more the context, the concerned application queries are mainly based on JDBC Prepared statements which imply using NVARCHAR(4000) with string parameters regardless the column type in the database (VARCHAR / NVARCHAR). This is at least what we noticed from during my investigations. </p>
<p>So, what? Well, in our DEV environment the impact was imperceptible, and we had interesting discussions with the DEV team on this topic and we basically need to improve the awareness and the visibility on this field. (Another discussion and probably another blog post) … </p>
<p>But chances are your PROD environment will tell you a different story when it comes a bigger workload and concurrent query executions. In my context, from an infrastructure standpoint, the symptom was an abnormal increase of the CPU consumption a couple of days ago. Usually, the CPU consumption was roughly 20% up to 30% and in fact, the issue was around for a longer period, but we didn’t catch it due to a &laquo;&nbsp;normal&nbsp;&raquo; CPU footprint on this server. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-3-SQL-Processor-dashboard.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-3-SQL-Processor-dashboard.jpg" alt="162 - 3 - SQL Processor dashboard" width="668" height="631" class="alignnone size-full wp-image-1612" /></a></p>
<p>So, what happened here? We&rsquo;re using SQL Server 2017 with Query Store enabled on the concerned database. This feature came to the rescue and brought attention to the first clue: A query plan regression that led increasing IO consumption in the second case (and implicitly the additional CPU resource consumption as well).</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-4-QS-regression-plan-e1590597560224.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-4-QS-regression-plan-e1590597560224.jpg" alt="162 - 4 - QS regression plan" width="1000" height="575" class="alignnone size-full wp-image-1613" /></a></p>
<p>You have probably noticed both the execution plans are using an index scan at the right but the more expensive one (at the bottom) uses a different index strategy. Instead of using the primary key and clustered index (PK_xxx), a non-clustered index on the IX_xxx_Identifier column in the second query execution plan is used with the same CONVERT_IMPLICIT issue. </p>
<p>According to the query store statistics, number of executions per business day is roughly 25000 executions with ~ 8.5H of CPU time consumed during this period (18.05.2020 – 26.05.2020) that was a very different order of magnitude compared to what we may have in the DEV environment <img src="https://blog.developpez.com/mikedavem/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>At this stage, I would say investigating why a plan regression occurred doesn’t really matter because in both cases the most expensive operator concerns an index scan and again, we expect an index seek. Getting rid of the implicit conversion by using VARCHAR type to make the conditional clause sargable was a better option for us. Thus, the execution plan would be:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-7-Execution-plan-with-seek-e1590597830429.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-7-Execution-plan-with-seek-e1590597830429.jpg" alt="162 - 7 - Execution plan with seek" width="1000" height="158" class="alignnone size-full wp-image-1615" /></a></p>
<p>The first workaround in mind was to force the better plan in the query store (automatic tuning with FORCE_LAST_GOOD_PLAN = ON is disabled) but having discussed this point with the DEV team, we managed to deploy a fix very fast to address this issue and to reduce drastically the CPU consumption on this SQL Server instance as shown below. The picture is self-explanatory: </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-6-SQL-Processor-dashboard-after-optimization-e1590597880869.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-6-SQL-Processor-dashboard-after-optimization-e1590597880869.jpg" alt="162 - 6 - SQL Processor dashboard after optimization" width="1000" height="460" class="alignnone size-full wp-image-1616" /></a></p>
<p>The fix consisted in adding CAST / CONVERT function to the right side of the equality (parameter and not the column) to avoid side effect on the JDBC driver. Therefore, we get another version of the query and a different query hash as well. The query update 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;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DECLARE @P0 DATETIME <br />
DECLARE @P1 INT<br />
DECLARE @P2 NVARCHAR(4000) <br />
DECLARE @P3 DATETIME <br />
DECLARE @P4 NVARCHAR(4000)<br />
<br />
UPDATE TABLE SET DATE = @P0<br />
WHERE ID = @P1<br />
&nbsp;AND IDENTIFIER = CAST(@P2 AS varchar(50))<br />
&nbsp;AND P_DATE &amp;gt;= @P3<br />
&nbsp;AND W_O_ID = (<br />
&nbsp; &nbsp;SELECT TOP 1 ID FROM TABLE2<br />
&nbsp; &nbsp;WHERE Identifier = CAST(@P4 AS varchar(50))<br />
&nbsp; &nbsp;ORDER BY ID DESC)</div></div>
<p>Sometime later, we gathered query store statistics of both the former and new query to confirm the performance improvement as shown below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/05/162-5-QS-stats-after-optimization.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/05/162-5-QS-stats-after-optimization.jpg" alt="162 - 5 - QS stats after optimization" width="923" height="98" class="alignnone size-full wp-image-1617" /></a></p>
<p>Finally changing the data type led to enable using an index seek operator to reduce drastically the SQL Server CPU consumption and logical read operations by far. </p>
<p>QED!</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>Collaborative way and tooling to debug SQL Server blocked processes scenarios</title>
		<link>https://blog.developpez.com/mikedavem/p13186/devops/collaborative-way-and-tooling-to-debug-sql-server-blocked-processes-scenarios</link>
		<comments>https://blog.developpez.com/mikedavem/p13186/devops/collaborative-way-and-tooling-to-debug-sql-server-blocked-processes-scenarios#comments</comments>
		<pubDate>Thu, 30 Jan 2020 14:13:48 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[Extended events]]></category>
		<category><![CDATA[locks]]></category>
		<category><![CDATA[orphan transactions]]></category>
		<category><![CDATA[sp_WhoIsActive]]></category>
		<category><![CDATA[sqlserver]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1437</guid>
		<description><![CDATA[A quick blog post to show how helpful an extended event and few other tools can be to help fixing orphan transactions in a real use case scenario. I often gave training with customers about SQL Server performance and tools, &#8230; <a href="https://blog.developpez.com/mikedavem/p13186/devops/collaborative-way-and-tooling-to-debug-sql-server-blocked-processes-scenarios">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A quick blog post to show how helpful an extended event and few other tools can be to help fixing orphan transactions in a real use case scenario. I often gave training with customers about SQL Server performance and tools, but I noticed how difficult it can be to explain the importance of a tool if you only explain theory without any illustration with a real customer case.<br />
Well, let’s start my own story that began a couple of days ago with an SQL alert to indicate a blocking scenario issue. Looking at our SQL dashboard (below), we were able to confirm quickly we are running into an annoying issue and it would be getting worse over if we do nothing.</p>
<p><span id="more-1437"></span></p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/01/153-1-SQL-dashboard.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/01/153-1-SQL-dashboard.jpg" alt="153 - 1 - SQL dashboard" width="1339" height="669" class="alignnone size-full wp-image-1438" /></a></p>
<p>&#8230;</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/01/153-2-SQL-dashboard.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/01/153-2-SQL-dashboard.jpg" alt="153 - 2 - SQL dashboard" width="1874" height="663" class="alignnone size-full wp-image-1439" /></a></p>
<p>Let’s precise before continuing there are a plenty of tools to help digging into blocked processes scenarios and my intention is not to favor one specific tool over another one. So, in my case the first tool I used was the <a href="http://whoisactive.com/" rel="noopener" target="_blank">sp_WhoIsActive</a> procedure from Adam Machanic. One great feature of it is to get a comprehensive picture of what is happening on your system at the moment you’re executing the procedure.<br />
Here a sample of output I got. Let’s precise it doesn’t reflect exactly my context (which was a little more complex) but anyway my intention is not to focus on this specific part  </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/01/153-3-sp_WhoIsActive.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/01/153-3-sp_WhoIsActive.jpg" alt="153 - 3 - sp_WhoIsActive" width="1339" height="328" class="alignnone size-full wp-image-1440" /></a></p>
<p>As you may see, I got quickly interesting information about the blocking leaders including session_id, the application name and the command executed as this moment. But the interesting part of this story was to get a request_id to NULL as well as a status value to SLEEPING. After some researches, having these values indicate likely that SQL Server has completed the command and the connection is waiting for the next command to come from the client. In addition, looking at the open_tran_count value (=1) confirmed the transaction was still opened. We started monitoring the transaction a couple of minutes to see if the application could manage to commit (or to rollback) the transaction but nothing happened. So, we had to kill the corresponding session to get back to a normal situation. A few minutes later, the situation came back with the same pattern and we applied the same temporary fix (KILL session).<br />
The next step consisted in discussing with the DEV team to fix this annoying issue once and for all. We managed to reproduce this scenario in DEV environment, but it was not clear what happened exactly inside the application because we got not specific errors even when looking at the tracing infrastructure. To help the DEV team investigating the issue, we decided to create a special extended event session that both monitor all activity scoped to the concerned application and the transactions that remain open during the tracing timeframe. Events will be easily correlated relying on causality tracking capabilities of extended events.  </p>
<p>So, the extended event session used two targets including the Event File and Histogram. Respectively, the first one was intended to write workload activity into a file on disk and the second one aimed identifying quickly opened transactions.</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">CREATE EVENT SESSION [OrphanedTransactionHunter] ON SERVER <br />
ADD EVENT sqlserver.database_transaction_begin(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.database_transaction_end(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.error_reported(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.module_end(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.module_start(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.rpc_completed(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.rpc_starting(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.sp_statement_completed(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.sp_statement_starting(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.sql_statement_completed(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.tsql_stack)),<br />
ADD EVENT sqlserver.sql_statement_starting(<br />
&nbsp; &nbsp; ACTION(sqlserver.database_id,sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_stack))<br />
ADD TARGET package0.event_file(SET filename=N'OrphanedTransactionHunter'),<br />
ADD TARGET package0.pair_matching(SET begin_event=N'sqlserver.database_transaction_begin',begin_matching_actions=N'sqlserver.session_id',end_event=N'sqlserver.database_transaction_end',end_matching_actions=N'sqlserver.session_id',respond_to_memory_pressure=(1))<br />
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)<br />
GO</div></div>
<p>The outputs were as follows:</p>
<p>&gt; Target histogram (with opened transactions)</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/01/153-4-xe-event-histogram.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/01/153-4-xe-event-histogram.jpg" alt="153 - 4 - xe event histogram" width="1473" height="69" class="alignnone size-full wp-image-1441" /></a></p>
<p>The only transaction that remained opened during our test (just be careful other noisy records not relevant at the moment when you start the XE session) concerned the session_id = 873. The attach_activity_id, attach_activity_id_xfer and session column values were helpful here to correlate events recorded to the event file target. </p>
<p>&gt; Event File (Workload activity)</p>
<p>Here the events after applying a filter with above values. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/01/153-5-xe-event-file.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/01/153-5-xe-event-file.jpg" alt="153 - 5 - xe event file" width="1333" height="303" class="alignnone size-full wp-image-1442" /></a></p>
<p>We noticed the transaction with session_id = 873 was started but never ended. In addition, we were able to identify the sequence of code executed by the application (mainly based on prepared statement and stored procedures in our context).This information helps the DEV team to focus on the right portion of code to fix. Without getting into details, it was very interesting to see this root cause was a SQL statement and duplicate key issue not thrown and managed correctly by the application. I was just surprised the application didn’t catch any errors in a such case. We finally understood that prepared statements and stored procedure calls were done through the DButils class including the closeQuietly() method to close connections. Referring to the <a href="https://commons.apache.org/proper/commons-dbutils/apidocs/org/apache/commons/dbutils/DbUtils.html" rel="noopener" target="_blank">Apache documentation</a>, closeQuietly() was designed to hide SQL Exceptions when happen which definitely not help identifying easily the issue from an application side. Never mind, thanks to the collaboration with the DEV team we managed to get rid of this issue <img src="https://blog.developpez.com/mikedavem/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" /></p>
<p>David Barbarin </p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Expérimentation d&#8217;une mise à jour de statistiques sur une grosse table par des voies détournées</title>
		<link>https://blog.developpez.com/mikedavem/p13167/sql-server-2014/experimentation-dune-mise-a-jour-de-statistiques-sur-une-grosse-table-par-des-voies-detournees</link>
		<comments>https://blog.developpez.com/mikedavem/p13167/sql-server-2014/experimentation-dune-mise-a-jour-de-statistiques-sur-une-grosse-table-par-des-voies-detournees#comments</comments>
		<pubDate>Thu, 25 Jan 2018 06:52:08 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[sqlserver]]></category>
		<category><![CDATA[statistiques]]></category>
		<category><![CDATA[TF7471]]></category>
		<category><![CDATA[update statistic]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1375</guid>
		<description><![CDATA[Ceci est mon premier blog de l&#8217;année 2018 et depuis un moment d&#8217;ailleurs. En effet, l&#8217;année dernière j&#8217;ai mis toute mon énergie à réajuster mes connaissances Linux avec la nouvelle stratégie Open Source de Microsoft. Mais en même temps, j&#8217;ai &#8230; <a href="https://blog.developpez.com/mikedavem/p13167/sql-server-2014/experimentation-dune-mise-a-jour-de-statistiques-sur-une-grosse-table-par-des-voies-detournees">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Ceci est mon premier blog de l&rsquo;année 2018 et depuis un moment d&rsquo;ailleurs. En effet, l&rsquo;année dernière j&rsquo;ai mis toute mon énergie à réajuster mes connaissances Linux avec la nouvelle stratégie Open Source de Microsoft. Mais en même temps, j&rsquo;ai réalisé un certain nombre de tâches intéressantes chez certains clients et en voici une pour commencer cette nouvelle année. Dans ce billet, j&rsquo;aimerai souligner une approche particulière (selon moi) pour optimiser une mise à jour de statistiques pour une grosse table.</p>
<p>&gt; <a href="https://blog.dbi-services.com/experiencing-updating-statistics-on-a-big-table-by-unusual-ways/" 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>Lorsqu&#8217;une recherche d&#8217;index n&#8217;est pas forcément adéquate</title>
		<link>https://blog.developpez.com/mikedavem/p13111/sql-server-2005/lorsquune-recherche-dindex-nest-pas-forcement-adequate</link>
		<comments>https://blog.developpez.com/mikedavem/p13111/sql-server-2005/lorsquune-recherche-dindex-nest-pas-forcement-adequate#comments</comments>
		<pubDate>Thu, 13 Oct 2016 18:35:29 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2005]]></category>
		<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[index seek]]></category>
		<category><![CDATA[partial scan]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[sqlserver]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1274</guid>
		<description><![CDATA[N&#8217;avez-vous jamais considéré une recherche d&#8217;index comme un problème? Laissez moi vous raconter une histoire avec un de mes clients avec un contexte simple: une requête spécifique qui n&#8217;était pas dans les valeurs acceptables de performance exigées (environ 200ms de &#8230; <a href="https://blog.developpez.com/mikedavem/p13111/sql-server-2005/lorsquune-recherche-dindex-nest-pas-forcement-adequate">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>N&rsquo;avez-vous jamais considéré une recherche d&rsquo;index comme un problème? Laissez moi vous raconter une histoire avec un de mes clients avec un contexte simple: une requête spécifique qui n&rsquo;était pas dans les valeurs acceptables de performance exigées (environ 200ms de temps d&rsquo;exécution moyen). Le plan d&rsquo;exécution associé de la requête était similaire à ce que vous pouvez voir ici</p>
<p>&gt; <a href="http://blog.dbi-services.com/when-index-seek-operation-is-not-always-your-friend/" 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>Changement une partition existante &#8230; pas si facile que cela</title>
		<link>https://blog.developpez.com/mikedavem/p13004/sql-server-2014/changement-une-partition-existante-pas-si-facile-que-cela</link>
		<comments>https://blog.developpez.com/mikedavem/p13004/sql-server-2014/changement-une-partition-existante-pas-si-facile-que-cela#comments</comments>
		<pubDate>Thu, 03 Mar 2016 05:25:03 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[MERGE]]></category>
		<category><![CDATA[mouvement de données]]></category>
		<category><![CDATA[partition]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[SPLIT]]></category>
		<category><![CDATA[sqlserver]]></category>
		<category><![CDATA[SWITCH]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1179</guid>
		<description><![CDATA[Cette fois, parlons d&#8217;un cas client intéressant avec une table partitionnée de 100 GB sous SQL Server 2014. Dans ce contexte, le partitionnement avait pour objectif de sauvegarder de l&#8217;espace disque (données d&#8217;archives compressées), aider à réduire les temps de &#8230; <a href="https://blog.developpez.com/mikedavem/p13004/sql-server-2014/changement-une-partition-existante-pas-si-facile-que-cela">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Cette fois, parlons d&rsquo;un cas client intéressant avec une table partitionnée de 100 GB sous SQL Server 2014. Dans ce contexte, le partitionnement avait pour objectif de sauvegarder de l&rsquo;espace disque (données d&rsquo;archives compressées), aider à réduire les temps de maintenance ainsi et les ressources consommées (utilisation des opérations d&rsquo;index et de statistiques à la partition). Par la même occasion, cela aidera à améliorer les performances de requête sur la table concernée qui se concentre uniquement que sur les commandes récentes des clients. </p>
<p>&gt; <a href="http://blog.dbi-services.com/changing-an-existing-partition-configuration-well-not-so-easy/" 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>
