Friday Reading 2017-05-05

Into May and a big couple of events this week in SQL Nexus and the Powershell Conference EU 2017, looking forward to more blog posts coming out about those events. This week I’ve been reading: –

SQL Nexus 2017 Conference Recap
Sam Lester recaps his experience at SQL Nexus and gives us a summary of the two sessions he presented.

Database backups with DBATools vs Ola Hallengren’s scripts
Nice comparison between two database backup options

Dear McAfee, why are you destroying my buffer pool?
Good post about anti-virus paging out all running process when updating

Azure SQL or SQL Server Database?
Old post but good in that it details the differences between Azure SQL and standard SQL Server databases

The LHC was restarted for its 2017 run
The LHC has been shut down over the winter so that improvements/maintenance can be made. This article details what’s been done and what they hope to accomplish this year.

Have a good weekend!

Building a container running SQL Server 2014 SP2 Developer

One of the things about working with SQL in Docker is that you kinda have to use the images that are on the Docker Hub. Now this is great if you want SQL Server 2016 or 2017 but what about earlier versions?

Now, this is a bit involved so I should point out WinDocks.com. They have a great product which allows earlier versions of SQL Server to run in containers on earlier versions of Windows Server which means you don’t have to go through all this.

But I wanted to try this to see if I could get it done. I’ve noticed that there aren’t any images for SQL Server 2014 SP2 Developer Edition on the Docker Hub (not that I can find anyway) so I thought I’d build one myself.


TL;DR – If you want to skip all of this you can download the image I’ve build from the Docker Hub by running:-

docker pull dbafromthecold/sqlserver2014dev:sp2

I’m running all of this on my Windows 10 machine but there are a few things you’ll need before we get started: –

Pre-requisites

  • The microsoft/windowsservercore image downloaded from the Docker Hub
  • Windows Server 2016 installation media extracted to
    C:\Docker\Builds\Windows
  • SQL Server 2014 SP2 Developer Edition installation media extracted to C:\Docker\Builds\SQLServer2014\sql_server_2014_dev_sp2

First thing to do is build an image of Windows Server 2016 Core with .Net 3.5 installed. So first we will create a container running windows server 2016 with the installation media copied into it. Then we’ll install .Net 3.5.

So, build the container: –

docker run -it -v C:\Docker\Builds\Windows\en_windows_server_2016_x64_dvd_9718492\sources:C:\install --name buildcontainer1 microsoft/windowsservercore

This will copy the files under the source folder to C:\install within the container. Once the container is up and running, the -it switch will open a remote session into the container. So then we run: –

cd c:\install

powershell

Install-WindowsFeature –name NET-Framework-Core –source c:\install\sources\sxs 

Cool, so exit out of that container and commit it as a new image: –

docker commit buildcontainer1 windowscorenet

I then tagged the image with my docker repository name so that I could push it to the cloud (so that you can use it): –

docker tag windowscorenet dbafromthecold/windowsservercore:v1

Now that we have the base image created we can build an image running SQL Server 2014 from a dockerfile.

Here’s the code in the dockerfile: –

# using my windows server core image
FROM dbafromthecold/windowsservercore:v1

LABEL maintainer "Andrew Pruski"

# create directory to hold iso
RUN powershell -Command (mkdir C:\SQL2014)

# copy media into container
COPY sql_server_2014_dev_sp2 C:\SQL2014

# install SQL Server
RUN C:\SQL2014\setup.exe /q /ACTION=Install /FEATURES=SQLENGINE /INSTANCENAME=MSSQLSERVER /SECURITYMODE=SQL /SAPWD=Testing1122 /SQLSVCACCOUNT="NT AUTHORITY\System" /SQLSYSADMINACCOUNTS="BUILTIN\Administrators" /TCPENABLED=1 /IACCEPTSQLSERVERLICENSETERMS

# remove installation media
RUN powershell -Command (rm C:\SQL2014 -recurse)

# make sure service is set to automatic
RUN powershell -Command (set-service MSSQLSERVER -StartupType Automatic)

# switch shell to powershell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

COPY start.ps1 /
WORKDIR /

ENV SA_PASSWORD _
ENV ACCEPT_EULA _

# run start.ps1
CMD .\start -sa_password $env:SA_PASSWORD -ACCEPT_EULA $env:ACCEPT_EULA -Verbose

N.B. – this is available on my Github here

Most of the code is self-explanatory but I do want to mention the final few lines: –

# switch shell to powershell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

COPY start.ps1 /
WORKDIR /

ENV SA_PASSWORD _
ENV ACCEPT_EULA _

# run start.ps1
CMD .\start -sa_password $env:SA_PASSWORD -ACCEPT_EULA $env:ACCEPT_EULA -Verbose

This switches the shell to use powershell. I didn’t do this earlier in the dockerfile as trying to install SQL 2014 using powershell kept throwing errors. Once we’re using powershell it then copies a script called start.ps1 into the container.

This script is a slightly modified version of the script from the official Microsoft Github repository

Here’s the code for the script: –

# script from offical MS repo: - https://github.com/Microsoft/mssql-docker/blob/master/windows/mssql-server-windows/start.ps1

param(
[Parameter(Mandatory=$false)]
[string]$sa_password,

[Parameter(Mandatory=$false)]
[string]$ACCEPT_EULA
)


if($ACCEPT_EULA -ne "Y" -And $ACCEPT_EULA -ne "y")
{
	Write-Verbose "ERROR: You must accept the End User License Agreement before this container can start."
	Write-Verbose "Set the environment variable ACCEPT_EULA to 'Y' if you accept the agreement."

    exit 1
}

# start the service
Write-Verbose "Starting SQL Server"
start-service MSSQLSERVER

if($sa_password -ne "_")
{
    Write-Verbose "Changing SA login credentials"
    $sqlcmd = "ALTER LOGIN sa with password=" +"'" + $sa_password + "'" + ";ALTER LOGIN sa ENABLE;"
    & sqlcmd -Q $sqlcmd
}


Write-Verbose "Started SQL Server."

$lastCheck = (Get-Date).AddSeconds(-2) 
while ($true) 
{ 
    Get-EventLog -LogName Application -Source "MSSQL*" -After $lastCheck | Select-Object TimeGenerated, EntryType, Message	 
    $lastCheck = Get-Date 
    Start-Sleep -Seconds 2 
}

The script runs when a container starts and performs the following actions: –
– Checks that the end user licence agreement has been accepted
– Changes the SA password
– Start a infinite loop

Now, what’s with the infinite loop? Well, without this the container (when spun up with the -d flag) will auto-close immediately. Docker containers need some defined process to be running otherwise they will shut down.

I fully admit that this is kinda hacky and not great. But that’s how Microsoft have stopped containers from auto-closing and I’ve been looking into this quite a bit and haven’t been able to come up with any other ways.

Also, it does mean that we can run SQL commands automatically when a container starts up (that’s how the SA password is changed). I’m going to have a think on that as I’m pretty sure there’s some cool stuff that can be done.

Anyway now we can build the image, so run: –

docker build -t sqlserver2014dev:sp2 C:\Docker\Builds\SQLServer2014

Awesome stuff! But has it worked? Can we spin up a new container and have SQL 2014 up and running? Let’s give it a whirl: –

docker run -d -i -p 14567:1433 --env ACCEPT_EULA=Y --SA_PASSWORD=Testing1122 --name testcontainer2014 sqlserver2014dev:sp2

Now we need to get the IP address that the container is listening on: –

Update – April 2018
Loopback has now been enabled for Windows containers, so we can use localhost,14567 to connect locally. You can read more about it here

docker inspect testcontainer2014

My container is listening on port 172.26.126.99 so I’ll open up SSMS on my local machine, enter the sa username/password and: –

SQL Server 2014 SP2 Developer Edition running in a container that’s been build from a custom image. Cool, eh?

What I like is that I’ve used this dockerfile as a base to build a SQL Server 2012 image as well. You can view all the images I’ve pushed to the Docker Hub by running: –

docker search dbafromthecold

And if you want to build an image yourself, all the different dockerfiles I’ve created are on my Github

Thanks for reading!

Monday Coffee 2017-05-01

Morning all, I know it’s a bank holiday in the UK & Ireland today but some of us still have to work.

Ha, only joking. I wrote this yesterday and am probably still in bed at this very moment!

Couple of cool things have happened over the weekend. The first one is that I finally bought the domain for this site, dbafromthecold.com
I held off on this for too long really, I keep telling myself that I wanted to see if I stuck with blogging before I bought it but it’s been 3 years now so I guess it was about time 🙂

The second thing is that my session on SQL Server & Containers got selected for the next BrentOzar.com GroupBy session.

This will be the first time that I’ve done a full online session and I’m really looking forward to it. I’ve moderated a couple of 24 hours of PASS sessions but running my own one will be a completely different ball game.

I think online sessions are great. Not everyone can get to in-person events so this will allow a lot more people to get training in areas that they are either working with and want to learn more or want to be exposed to something completely new.

I’ve always said that I’ve benefited immensely from the SQL Server community so doing a session like this is my way of giving something back.

Have a good week!

Friday Reading 2017-04-28

Nearly May! Although it’s been snowing this week in Dublin so summer still appears to be a while off…

Community driven Enhancements in SQL Server 2017
The MS Tiger Team list the new features in SQL 2017 that have been built based on feedback from the community

SQL Server 2017 – Adaptive Query Processing
Joe Sack takes us through a new (and really cool imho) feature in SQL 2017

SQL Community Scripts
Shane O’Neill has put together a handy list of all the scripts available out there

Why Did Your Availability Group Creation Fail?
Anthony Nocentino takes us through an error that he encountered when setting up an Availability Group (I like posts about real world issues and resolutions)

Have a good weekend!

Pausing index rebuilds in SQL Server 2017

Last week Microsoft confirmed that the name of SQL vNext will indeed be SQL Server 2017. I was looking through the documentation for more info on Adaptive Query Processing as I wanted to write a post on adaptive joins but then I saw: –

To see the new Adaptive Join operator in Graphical Showplan, a new version of SQL Server Management Studio is required and will be released shortly.

Source

Ok, I’ll wait! So I went back to the list of new features in SQL 2017 and something else caught my eye. The ability to pause and then resume online index rebuilds.

Sounds pretty cool, let’s see it in action. Here’s the setup: –

(SQL Server 2017 can be downloaded from here btw)

USE [master];
GO

CREATE DATABASE [Test]
GO

ALTER DATABASE [Test] SET COMPATIBILITY_LEVEL = 140
GO

That’s the database created and put into the correct compatibility level (just to be sure). Now let’s create a table to test with: –

USE [Test];
GO

CREATE TABLE [TestTable]
(PKID INT IDENTITY(1,1) CONSTRAINT PK_Test PRIMARY KEY CLUSTERED,
 ColA VARCHAR(10),
 ColB VARCHAR(10),
 ColC VARCHAR(10),
 ColD DATETIME)


SET NOCOUNT ON;
INSERT INTO [TestTable]
(ColA,ColB,ColC,ColD)
VALUES
(REPLICATE('A',10),REPLICATE('B',10),REPLICATE('C',10),GETUTCDATE())
GO 100000

OK, now let’s rebuild the clustered index that we’ve created on the table: –

ALTER INDEX [PK_Test] ON [TestTable] REBUILD WITH (ONLINE=ON,RESUMABLE=ON);
GO

N.B. – notice the new option RESUMABLE=ON

Whilst that’s running, open a new connection and run: –

USE [Test];
GO

ALTER INDEX [PK_Test] ON [TestTable] PAUSE;
GO

The session that running the rebuild should now have stopped with the rather disconcerting error: –

Looks pretty worrying imho! But not to stress, jump back to your other connection and run: –

ALTER INDEX [PK_Test] ON [TestTable] RESUME;
GO

Hmm, but how do I tell that this has worked? Well, if you have sp_whoisactive on your instance you can verify that the query is re-running: –

Pretty cool, huh? Full information on this can be found here: – https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-index-transact-sql

I think this is very useful but we do need to be careful. The documentation says that pausing an online index rebuild for a long time may affect query performance and disk utilisation. This is due to the newly rebuild index being created side-by-side to the original one so we’ll need to watch out for that.

Thanks for reading!