Introduction To PowerShell For The DBA Part 2

In Part 1 of this series we began to look at how you can leverage PowerShell as a DBA and there was a brief discussion about automation. Today you will experiment with the DBATools command Copy-DbaLogin and learn about Out-Gridview and the -whatif switch.

Let’s suppose you have one, or more logins you need to get from one SQL instance to another.  Perhaps you are setting up a new test environment for SQL Server 2019 and you need  to move this login to that environment. Maybe this is one node of a SQL Server AlawaysOn Availability Group and you need to get this login, with its SID, on each node of the AG. Below you see I have a screenshot of a login called mysqltestlogin. It’s on a SQL Server 2017 instance.

 

How would we copy this with PowerShell? First, let’s use the Get-Help command to see what commands are available related to logins.

Get-Command *login* -module DBATools, sqlserver

From that output you see a command called Copy-DBAlogin in the DBATools module.

So now run the first command to see the syntax and run the second one to see all the help data, including some examples of how the command works:

Help Copy-DBALogin

Help Copy-DBALogin -Full

The most common way you’re going to use this command is with a Source and Destination SQL Server name and one or more login names. See the example below.

These logins can be SQL logins or Active Directory Logins. One thing to note about this command is that the SID is copied with the login as well as the associated permissions. If you need to, you can use the -Force switch to re-copy an existing login. You might need to do this to ensure that logins, SIDs and permissions are the same between all nodes involved in a group of servers. Those SQL Servers could stand alone instances that are all servicing a particular application or they could be nodes in a Failover Cluster Instance or an Availability Group.

Copy-DBALogin -Source MySourceSQLServerIntanceName -Destination MyDestinationSQLServerInstanceName -Login Login1, Login2, Login3

Maybe you want to copy all the logins except a certain small list. In that case, use the -ExcludeLogin parameter and pass in the logins to omit from the copy operation.

For my scenario from above, my command looks like this.

Copy-DbaLogin -Source MyPCName\Kronos2017 -Destination MyPCName\Romulus2014 -Login mytestsqllogin

And the output is this.

DBATools Copy-DBALogin Output

 

What Is Out-GridView?

You can also use a cmdlet called Out-GridView to pass the objects of the pipeline into a GUI where you can then select the items you want to have PowerShell do the action against.

Get-DBALogin -Sqlinstance MySourceSQLInstance | Out-GridView -PassThru | Copy-DBALogin -Destination MyDestinationSQLInstance

Here are the results of that Out-GridView. Click to enlarge.

Out-GridView Example

To use this for selecting only the rows of output that you want to do something with, left click the row you want to actually copy and then click the OK button in the bottom right. That will copy the selected row. You can use Shift + Click or Control + Click to do a multi-select. There is a Filter option at the top of the Out-GridView screen that also allows you to trim down the results you want to copy.

Of course, using Out-GridView re-introduces the human element to the process and so isn’t great when the goal is to completely automate a process. However, it is great if you want to see the output before you do something you don’t want to do. As a consequence, if you see results in Out-GridView that don’t match what you expect, then you can simply click on Cancel in the lower right hand corner and the PowerShell will do nothing.

Using the -WhatIf Switch In PowerShell

This brings me to another switch that helps in this scenario where you want to see what a command is going to do before you actually executing it. There is a switch called -WhatIf that will stream output showing you what a command would do if it were actually executed. This is a great tool for testing your commands. Often there will be errors or other unexpected results from a command. Using -WhatIf is a great way to catch this before you actually execute the command for real.

So far in this article, you have reviewed what you can do for a very specific object, logins. Let me suggest that you also look at what can be done at the wider scope of the SQL Server level by running the below. You may remember from the previous post that GCM is an alias for the Get-Command cmdlet.

GCM *instance* -Module DBATools, SQLServer

Here is my output for the above. Click to enlarge.

Get-Command Instance :evel Commands

As you see, there are a lot of things you can do with commands related to the SQL Server Instance.

If you want to consider automating the scripting out of your SQL Server instance objects without buying software to do it, then check out the Help for Export-DBAInstance, which is one of the commands that is in the above list.

Help Export-DbaInstance -Full

 

Next Steps To Take

  1. Try out Copy-DBALogin in a test environment. Use it with the -WhatIf switch, or pipe it to a file by using the Out-File command to see what the command does when it runs.
  2. Experiment with various commands and Out-GridView in your test SQL Server environment.
  3. Don’t have a test SQL Server environment? Consider learning what Export-DBAInstance does and using it as part of an “Easy button” for creating a test environment on a fresh install of SQL Server. Or, look up Start-DBAMigration for this task as well.
  4. If you would like help with anything in this post, or with something else related to SQL Server, reach out to me here, or on Twitter, and I’ll be glad to offer assistance.

Introduction To PowerShell for the DBA Part 1

Automating Tasks With PowerShell

What we’re really talking about in this series is automation, specifically by using PowerShell. Now, in simple terms, automation is about removing the human, manual element in doing tasks. This will produce time savings for you as a DBA in the long run and provide better consistency in your environment than doing things manually. Better consistency means reduced or easier troubleshooting because your SQL Server environment will be more consistent with automation. All of this will make your SQL Servers easier to manage.

Imagine being able to migrate an entire SQL Server instance with a single command! You can do this with PowerShell. You want to copy logins from one server to another without installing sp_help_revlogin and  working through the scripting process involved? You can do that with PowerShell.  You want to copy DatabaseMail settings from one server to other servers without writing out all the T-SQL? You can do that with PowerShell!

With PowerShell you can get information faster than from a GUI, especially when that task needs to be done on multiple computers. These tasks include things like like search event logs, search the SQL Server Error Log,  get the status of services, see sp_configure information and more.

You can also do things like copy SQL Server jobs from one server to another or export the results of sp_configure to a file. When doing an action like backing up a database, PowerShell also enables you to output the actions of the script itself and thereby create a self-documenting log that you can look at afterward to see exactly what the script did.  With a module called DBATools, you can migrate an entire instance to a new SQL Server with a single, short command.

Getting Set Up for Using PowerShell

PowerShell is already installed on Windows. Different OS versions have different versions of PowerShell. There is a process to use for updating your PowerShell version. I’ll not be showing that process in this series though.

Also, in order to follow along in the series. You will need to get the DBATools module for PowerShell. Instructions for doing that are located at DBATools.io. The simple answer is to open PowerShell as an Administrator and run the below command. There are some things to consider and so that’s why the link to DBATools instructions on installation.

Install-module DBAtools

 

You will want the SQLServer module in order for some of these commands to work properly, and you may want to explore the more “native” way to use PowerShell with SQL Server, without the aid of the DBATools module. I think DBATools simplifies things so immensely that it is indispensable. However, you may be curious about what is in the SQLServer module for PowerShell. If so, you can add the module to your PowerShell by opening  PowerShell as an administrator and running the following.

Install-Module -Name SqlServer

 

Once you have DBATools and the SQLServer module installed, you are ready to get started.

Finding Available PowerShell Commands

Get-Command: This cmdlet enables you to explore what is available to do in PowerShell.  For instance, you might run the below to see what commands are available in PowerShell related to backups. Notice you can use asterisks as wildcards as well as specify a PowerShell module to look in for commands. If you don’t have the DBATools module, I urge you to get it installed and start using it, if for no other reason than that you will need it if you’re going to follow along with the examples!

Get-Command *Backup* -Module DBATools, SqlServer

The above command will output a long list of things.  You can backup computer certificates, database certificates, find information about backup history and throughput, as well as a lot of other things beyond simply using PowerShell to make a database backup.

Maybe you’re interested in what is available for Logins or Database Mail. If so, try the below commands.  Notice that the second command says “gcm”.  What is that? Well, that is a shortened version, or alias, for Get-Command.  Most, maybe all commands, have an alias you can use.  Aliases provide a shorter way to write a command, but when someone else is looking at your code, then they have to know what your alias is for. Otherwise it will be harder to figure out what you’re code is doing.

Get-Command *Login*  -Module DBATools, SqlServer

gcm *mail*

Getting Help with PowerShell Commands

From the above example where you are looking for commands containing the word “Login”, you should see something similar to the below if you have DBATools and the SQLServer module installed.

 

Let’s start simple and review Get-DbaLogin.  In your PowerShell window run the command  below.

Get-Help Get-DBALogin -Detailed

From this code you will get an output that provides a summary of what the cmdlet does, the syntax options it can be used with and a text description of what those syntax options do.

Let’s say that you’re interested in finding information about the Logins on your SQL Servers. If you just pass this command to PowerShell you will get a list of all the logins on the SQL instance with some properties. Of course, you will want to substitute your own valid SQL Server instance name.

Get-DbaLogin -SqlInstance MySQLInstanceName

The output will list the computer name, SQL Server instance name, name of the login, the login type, create date, the last login timestamp and some other useful properties.

Let’s suppose we only cared about the logins that weren’t system logins so we want to exclude logins like NT Service\SQLWriter and the ones whose name starts with ##. How do we do that? Well, look at the help output again and notice the -ExcludeFilter option. Add that to the earlier command, like so:

Get-DbaLogin -SqlInstance MYSQLServerInsstane -ExcludeFilter '##*', 'NT*'

PowerShell Piping

Now let’s suppose that you are only interested in a couple of the properties that are output from this command.  You’re interested in the login name and the last time that login accessed this SQL Server.

To get only those properties we can do what is called “piping”.  This is where the “|” symbol is used to move PowerShell output from the left over to the right side of the script objects.  This is often done for filtering or to pass along PowerShell output for further processing by other commands.  PowerShell output looks like text, but it’s really .Net objects.

In the first example below, you’re passing all the objects left from Get-DbaLogin when the ones with ‘##*’ or ‘NT*’ are eliminated and then telling PowerShell to display only the Name and LastLogin objects.

In the second example, you will be sending the output of the command to a file.

Get-DbaLogin -SqlInstance MySQLServerInstance -ExcludeFilter '##*', 'NT*' | SELECT Name, LastLogin

Get-DbaLogin -SqlInstance Skolarlee-PC\KRONOS2017 -ExcludeFilter '##*', 'NT*' | SELECT Name, LastLogin | Out-File 'C:\DBATools\LoginsOutput.txt'

On my local PC this returns the sa account and my local Windows account along with the last time these accounts accessed the SQL Server. This sort of information is useful, probably in a number of scenarios, but let’s suppose that you’re doing an audit of SQL Server logins because you suspect you have a lot of left over, unused logins.  You might want to examine them to see if you can drop users and logins that are no longer being used.  This sort of thing makes your SQL Server easier to manage because you don’t have unused Logins and database users cluttering up your SSMS when you’re connected to a SQL Server.

Let’s suppose you don’t want or need to do something with this information right now, but you want to review it later, or provide it to someone else for review. What can you do? The simplest thing is to use the second command above to send the PowerShell objects to a text file by using the piping technique I mentioned earlier.  The directory in the Out-File command needs to exist already but the command will create the text file for you.  This information can be written to a share for your team to access later.  You can also do things like email this output to the team using a PowerShell command for email. If you run GCM *mail* in PowerShell, you will find a command that lets you do this.

How To Script Out SQL Server Logins With PowerShell

Another powerful thing that can be done with a one line PowerShell script is scripting out your logins and users.  This cmdlet from the DBATools module will create a script of your logins at the server level and their corresponding database users and all associated permissions. Look at the help for this command.

#Start by getting the help for the command
Help Export-DbaLogin -Detailed

Now that you have reviewed the help content, let’s try something.

Export-Dbalogin -SqlInstance MySQLServerInstanceNameHere -Path 'C:\DBATools\'

Now go to the C:\DBATools\ directory and double click the .sql file.  SQL Server Management Studio will launch and prompt you to connect to a SQL instance. Once you do that, the script will load. Review the output and take a look at the Help output from PowerShell to see what else you can do with this.  This command gives a DBA a great way to script out login and user information, and this can be helpful for migrations or for providing a history of changes to logins, users, and their permissions.

Next Steps To Take

  1. Explore more commands and the possibilities that they offer. Here is a place to start.
GCM *export* -Module DBATools

Help Export-DbaInstance -Detailed

Export-DbaInstance -SqlInstance MySQLServerInsanceNameHere -Path C:\DBATools\

2. Find a book or video series on PowerShell and consume that material.

3. Read some of the documentation and blogs over at dbatools.io .

4. If you would like help with anything in this post, or with something else related to SQL Server, reach out to me here, or on Twitter, and I’ll be glad to offer assistance.

SQL Server Install Guide Part 2

In part 1 of this series, I discussed pre-installation steps.  There are many guides available online for the actual installation process so I’m not going to give a step by step installation guide here.  Rather, I’m going to focus on what to think about after the install is complete.

Recent versions of SQL Server will now go out and download additional content for you before the install actually happens so you’re not left on the base, RTM release of the product.  However, one thing to consider post installation is still, are you on the latest patch?  How do you know?  Where can you go to compare the version number of the SQL Server you installed to what is currently available?  Well, you can look back at this post to answer that question.

Once you’ve determined whether or not additional patching is needed and completed that, then what?  Well, there is a lot of post install configuration still to do.  For example, do you need to migrate Linked Servers, SQL Agent jobs, SQL Operators?  What about setting up database mail or moving Logins?  Each one of these can take up a lot of time.  What if there was a quick way to handle those things?  Enter DBATools.

DBATools is a fantastic collection of hundreds of PowerShell commands that have been developed and tested by users worldwide.  With a simple command, linked servers can be migrated, with their password information intact. The same with SQL Server logins and their passwords and permissions.  Database mail? No problem!  In fact, if you call Start-DBAMigration and pass a source and target SQL instance, then you can migrate the entire instance in a single command.  DBATools is fantastic for ongoing maintenance tasks and a bunch of other things too so be sure to check out all that it can do for you as a DBA.

The next item on my install guide is trace flags.  Trace flags control the behavior of SQL Server in a variety of ways.  As one example, trace flag 3226 controls whether successful backups are logged in the SQL Sever error log.  Setting this flag prevents those “backup successful’ messages from cluttering up your error log.

The important thing to remember if you’re doing a migration is that you most likely want the new SQL Server to behave in the same way as the old one.  To find out what trace flags are globally enabled on a SQL Server, run the following code.

DBCC TRACESTATUS(-1)

If you want a list of trace flags and what they do, those lists do exist but they are sometimes hard to find.  Here is one such list that tells you whether you should be concerned about a particular trace flag being enabled or not.

If you’re starting from scratch with the database and application you’re installing, be sure to find out if the vendor has any recommendations and why they recommend those particular trace flags.  Also, do your own research about trace flag functionality and see why you personally may or may not want to use a particular flag.

 

Setting Min and Max Server Memory Setting

Configuring the min and max server memory settings for SQL Server has a number of things to consider prior to making changes. Before we jump into those considerations, let’s learn what the min and max server memory options do.

What does the min server memory option do?

The min server memory option specifies the minimum amount of memory utilized by the SQL Server buffer pool. It may seem that this should mean that when SQL Server starts it will automatically grab the memory equal to the min server memory value. However, this is not what happens. Instead, SQL Server acquires system memory as needed to process a workload. Consequently, if the SQL Server workload remains low, it is possible that the min server memory value is never reached. However, once it is reached SQL Server will not release an amount of memory that would take it below that minimum setting.

For example, let’s suppose your server has 128 GB of RAM and the min server memory option were set to 32 GB for SQL Server. SQL Server does not immediately allocate 32 GB of RAM upon serve startup. It will acquire memory as needed for the workload. This means that if there is little activity in the database it may take some time before SQL Server allocates 32 GB of RAM. Once this happens, SQL Server will not release memory that would reduce the allocation below the min serve memory setting.

What does the max server memory option do?

To a certain point the max server memory setting does do what it sounds like. Keep in mind this setting is applicable only to the buffer pool. SQL Server can allocate some memory beyond this max number as it consumes memory for things outside of the buffer pool. Also, realize that this setting does not account for memory allocated to other components of SQL Server that may be installed and running, such as Reporting Services or Analysis Services.

 

The default value for Max Server Memory is 2,147,483,647 in MB. That number is rather large, 2,047.99 GB to be exact. So what happens if the machine SQL Server is installed on does not have that much memory and the default was not changed? As previously mentioned, SQL Server will continue to acquire additional memory based on workload. As a result, SQL Server could make requests of Windows that puts the box under memory pressure as it essentially chokes the OS by leaving less and less memory for the OS. There are mechanisms in the Operating System that allow it to page out to disk some information in the SQL Server buffer pool.  This action means Windows can recover that memory for itself. This hurts SQL Server performance because disk IO is far slower than keeping operations in memory. Among other places, details on how this process works can be found here, which is a blog post discussing the Lock Pages In Memory feature. I will save that setting for discussion a later post.

 

You can calculate how much memory the Windows OS and other applications may need and then subtract that from the physical memory available. There are recommendations on the internet for such things. Whatever number you arrive at would then be set as the Max Server Memory setting in SQL Server. The Available MB perfmon counter should then be judiciously monitored to ensure that there is adequate free memory left on the box, at least 1-2 GB. That will allow plenty of memory for that person who just insists on using an RDP connection to do his or her work or for a new process to fire off without bringing the server to its knees.

 

For example, let’s say that your server has 128 GB of RAM. You may decide to allocate 12 GB for the OS. Perhaps you have a vendor app that needs 4 GB. You take 128-(12+4) and that leaves 112 GB of RAM. If you are running SQL Server 2008 R2 then the Max Server Memory setting can be set to a max value of 64 GB. That is per SQL instance. SQL Server 2012 Standard supports a maximum of 64 GB and SQL Server 2014 Standard supports 128 GB. If SQL Server 2014 Standard were installed in this scenario there would be a maximum of 112 GB that could potentially be allocated to the SQL Server buffer pool for the machine described above.   Setting this limit at 112 GB, followed by the aforementioned monitoring of the Available MB performance monitor counter, would help ensure that SQL Server does not hog memory from the Windows operating system.

 

Now that there is a foundational understanding of what the Min Server Memory and Max Server memory settings are and how they work, let’s look at how to set these options in SQL Server.

How to Set Min and Max Server Memory

First, there is the GUI. Open SQL Server Management Studio and connect to a SQL Server instance. Right click on the SQL Server instance name and then choose Properties. Now select the Memory page in the left pane  Manually change the values in the Minimum and Max Server Memory boxes.  Remember that this is in MB.  Then click OK in the lower right of the dialog box.  Also, remember that when you make changes in SSMS you can click the Script button at the top of the dialog and T-SQL for the particular changes will be generated for you.

 

Min and Max Server Settings

 

Second, these settings can be changed using T-SQL.  Here is an example script that sets the minimum to 12 GB and the Max to 32 GB.

 

EXEC sys.sp_configure N'show advanced options', N'1' RECONFIGURE WITH OVERRIDE

GO

EXEC sys.sp_configure N'min server memory (MB)', N'12288'

GO

EXEC sys.sp_configure N'max server memory (MB)', N'32768'

GO

RECONFIGURE WITH OVERRIDE

GO

EXEC sys.sp_configure N'show advanced options', N'0' RECONFIGURE WITH OVERRIDE

GO

Setting Max Server Memory With PowerShell

As a third option, you can use PowerShell to set the max server memory. I have a blog post here that is the beginning of a series on using PowerShell to manage SQL Server.

We’re going to look at Set-DBAMaxMemory from the DBATools module. Here is what the DBATools website has to say about this cmdlet in their documentation.

“Inspired by Jonathan Kehayias’ post about SQL Server Max memory (http://bit.ly/sqlmemcalc), this uses a formula to determine the default optimum RAM to use, then sets the SQL max value to that number.”

Here are some examples from the documentation from DBATools and from the Help commands available in PowerShell.

<# If you have a Central Management Server for you SQL environment, consider using this command to loop through all the SQL Servers and set the Max Server Memory where it is set to something larger than the total amount of RAM assigned to the server. #> 

Get-DbaRegServer -SqlInstance sqlserver | Test-DbaMaxMemory | Where-Object { $_.MaxValue -gt $_.Total } | Set-DbaMaxMemory 

<# If you have a Central Management Server for you SQL environment, consider using this command to loop through all the SQL Servers and set the Max Server Memory to this accepted formula created by a SQL Server expert. #> 

Get-DbaRegServer -SqlInstance sqlserver | Test-DbaMaxMemory | Set-DbaMaxMemory 

<# If you don't have a registered server then just use the below #> 

Test-DbaMaxMemory -SQLinstance SQLServerInstanceNameHere | Set-DbaMaxMemory

 

What to do next

  • Review these settings on your SQL Server instance and consider whether they need to be adjusted.
  • Monitor your Available MB setting to ensure your servers have plenty of free space.
  • Explore using PowerShell commands for setting this server memory option.
  • Contact me here or reach out to me on Twitter if you have questions about this post or other questions about SQL Server.