The following example shows how to search for the location of the powershell.exe executable: PS>Get-ChildItem c:\ -recurse powershell.exe SQL Server–Specific Tasks Before jumping into mo
Trang 1Where {$_.EntryType -eq “Error”}
PS>Get-EventLog Application -New 10| `
Where {$_.EntryType -eq “Error”}|Select-Object TimeWritten
The preceding example demonstrates another useful feature of the PowerShell pipeline
where you can join several commands together to get specific results First, only the 10
newest entries are retrieved; then a pipe is used to get only the entries classified as an
error, and finally, only the TimeWritten property is displayed
We mentioned WMI earlier in this chapter as a method for remote control and
adminis-tration of servers WMI is packed full of features that are useful for system adminisadminis-tration
A few examples of using PowerShell’s built-in WMI features are shown here
Getting a listing of all the fixed local logical drives:
PS>Get-WmiObject -query “select * from Win32_LogicalDisk where
DriveType=’3’”
Getting a listing of all the fixed remote logical drives:
PS>Get-WmiObject -computerName server -query
“select * from Win32_LogicalDisk where DriveType=’3’”
Getting a listing of all the local patches/hotfixes installed (the –computerName
para-meter could be used with a value to retrieve this information from a remote system):
PS>Get-WmiObject Win32_QuickFixEngineering
NOTE
Remote WMI connections may require that appropriate firewall rules be open in the
network and also with a client firewall on the remote system In addition, remote
WMI queries must also be authenticated By default, WMI queries use the current
user’s authentication credentials In some scenarios WMI authentication can be more
complicated
The preceding examples show only the beginning of all the things WMI can provide quick
access to Another common task is trying to find files or folders You can use the
Get-ChildItem cmdlet to recursively search through a directory structure The following
example shows how to search for the location of the powershell.exe executable:
PS>Get-ChildItem c:\ -recurse powershell.exe
SQL Server–Specific Tasks
Before jumping into more hardcore SQL Server PowerShell features, let’s briefly look at the
SQL Server event log Fortunately, the log simply contains text-based files, which
PowerShell can read You could use the Get-Content cmdlet to view the entire log, but
Trang 2instead you can use the Select-String cmdlet to look for a specific string or pattern in
the error log file First, you change the current location to the SQL Server log directory:
PS>Set-Location “C:\Program Files\Microsoft SQL Server”
PS>Set-Location (join-path $pwd “MSSQL10_50.MSSQLSERVER\MSSQL\Log”)
PS>Select-String “error” ERRORLOG
The PowerShell prompt in the preceding example is simply a generic one because the
preceding commands would work both in the default PowerShell console and in the SQL
Server PowerShell minishell
An example of taking this further would be to retrieve all the errors in the ERRORLOG file
When you use Get-Member and Format-List to look at the object output by
Select-String, the date is hidden inside a string in the Line property:
PS >
Select-String “error” ERRORLOG|foreach{$_.line}|where{$_ -match “^20*”}|
foreach{$date,$time=$_.split()[0],$_.split()[1];[datetime]$($date+” “+$time) }
PS >
The preceding example demonstrates how to look for the string ”error” in the current
SQL Server ERRORLOG file For all the lines that match, the Line property is passed along
the pipeline Next, based on some testing, it appears that you want to search only lines
that start with ”20*-” From that object, two values are retrieved: $_.split()[0] and
$_.split[1] These values are placed in the $date and $time variables, respectively From
there, they are recombined, and a type accelerator is used to indicate that this is a
date/time object, so any calculations against this value will be simplified What is finally
output is the time stamp showing when the error occurred
Using the Provider
Using the SQL Server provider can be very handy in navigating the system Starting
PowerShell from SSMS, DBAs can easily find their way through different objects as if
working with files and directories
When the SSMS is used to start PowerShell at the server level, the databases are down one
level, and from there tables and users, for example, can also be easily accessed
In the session shown in Figure 17.8, we navigated to a particular database and entered a
dir Tables command The output from the last command would scroll beyond the
current screen, so only the first part of the output is displayed
Creating a Database Table
Creating a database and a table are common tasks that a DBA may undertake You can
use T-SQL with the Invoke-SqlCmd cmdlet to do this, but a demonstration on how to do
this with the SQL Server PowerShell minishell using SMO is presented here to help you
better understand the new functionality that is available:
Trang 3FIGURE 17.8 Navigating the SQL Server provider
cd databases
$my_db=New-Object Microsoft.SqlServer.Management.Smo.Database
$my_db.Name=”my_database”
$my_db.Parent=(Get-Item )
$my_db.Create()
cd my_database
cd tables
$my_tbl=New-Object Microsoft.SqlServer.Management.Smo.Table
$my_tbl.Name=”my_table”
$my_tbl.Parent=(Get-Item )
$my_col=New-Object Microsoft.SqlServer.Management.Smo.Column
$my_col.Name=”my_column”
$my_col.Parent=$my_tbl
$my_col.DataType= ([Microsoft.SqlServer.Management.Smo.DataType]::Int)
$my_tbl.Columns.Add($my_col)
$my_tbl.Create()
In the preceding example, some new objects are created, some of their properties are set,
and some methods are called You can search for the particular SMO classes used in this
example to gain further information
In the future, there may be something like New-Database and New-Table cmdlets that help
to create a database and table, which would likely reduce the preceding code to fewer than
five lines
Performing a Database Backup
Another example that may be useful is performing a database backup using SMO Using
the AdventureWorks2008R2 database, you can back up the database using just a few lines:
$server=New-Object Microsoft.SqlServer.Management.Smo.Server
Trang 4$backup=new-object Microsoft.SqlServer.Management.Smo.Backup
$file=new-object Microsoft.SqlServer.Management.Smo.BackupDeviceItem
$file.Name=”C:\backup\AW_DB.bak”
$backup.Devices.Add($file)
$backup.Database=”AdventureWorks2008R2”
$backup.SqlBackup($server)
The preceding code could be copied into a ps1 file (for this example, assume it’s copied
to c:\temp\backup.ps1), and it could be changed to accept two arguments The preceding
code could be modified to the following code snippet so that it accepts parameters from
the command line:
param([string]$device=$(throw Write-Host “Device required”), [string]
$database=$(throw Write-Host “Database required”))
Write-Host “backup of $database to $device starting ”
$server=New-Object Microsoft.SqlServer.Management.Smo.Server
$backup=new-object Microsoft.SqlServer.Management.Smo.Backup
$file=new-object Microsoft.SqlServer.Management.Smo.BackupDeviceItem
$file.Name=$device
$backup.Devices.Add($file)
$backup.Database=$database
$backup.SqlBackup($server)
Write-Host “backup complete”
Get-Item $device
The changes in the preceding example introduce a new keyword, throw Without it, error
messages would be thrown to the console, but this might not help the end user to
under-stand why it failed For the purpose of printing feedback to the console, the Write-Host
and Get-Item cmdlets were also added to provide a limited amount of feedback and to
finally provide the details of the final backup file
Then to invoke the script, as shown in the following example, you simply need to pass
two parameters to the script: the names of the file to back up to and the database to
actu-ally back up
PS>$backup_to=”C:\backup\AdventureWorks2008R2.bak”
PS>$db=”AdventureWorks2008R2”
PS> c:\temp\backup.ps1 $backup_to $db
As an example of using a conditional statement in the preceding script, perhaps a check
could be done to see whether a backup has already been completed within the past seven
days To accomplish this, you would add this particular section of code just before the line
Write-Host “backup of $database to $device starting ”:
If((Test-Path $device) -and (Get-Item $device).LastWriteTime `
-gt (Get-Date).AddDays(-7)){
“Backup has been performed in last 7 days” Break
}
Trang 5In the preceding code, a conditional statement is added to accomplish the check The
AddDays() method is passed a negative number which subtracts days from the current
date
NOTE
When you use the param keyword, this section of code must be on the first
noncom-mented line in all scripts Otherwise, the PowerShell parser returns an error
Again, using SMO isn’t necessarily for beginners, but the good thing is that scripts can
easily be created and passed around The preceding example shows the bare minimum
required to do a database backup; several other options are available, and the preceding
code would actually overwrite the backup each time it is run There also isn’t any error
checking of any sort, which isn’t the best way to develop scripts
Along with the New-Database and New-Table cmdlets that may come in the future, maybe
a Start-DbBackup will be another good cmdlet to have available
Checking Server Settings
From the SSMS, by right-clicking on the SQL Server node and then starting a SQL Server
PowerShell session, you can open a console directly in the root of the default SQL Server
in the example
From here, you can easily obtain information on the SQL Server First, the location is set to
the instance that is to be queried, and then an object representing the SQL Server is saved
to a variable (this demonstrates the advanced features mentioned earlier where objects can
be saved to variables) The properties of that variable can then be accessed as follows:
PS>Set-Location SQLSERVER:\SQL\<servername>\<instance_name>
PS>$sql_server=get-item
PS>$sql_server.Information.VersionString
Using the Get-Member cmdlet discussed earlier, you can easily discover other members of
the object contained in $sql_server, but this is left as an exercise for you to perform on
your own
NOTE
This example demonstrates an important feature of the SQL Server provider: context
sensitivity In the preceding example, the current location was in the root of the SQL
Server provider or database, and the command Get-Item was used The dot in this
command basically indicates that you want an object that represents the current
loca-tion in the provider If the dot were moved to a different localoca-tion, this command would
no longer work the same way
Trang 6Checking the Database Usage
Using the object retrieved in the $sql_server variable, you can create a quick report of
database usage using the databases property of that object, as shown here:
PS SQLSERVER:\SQL\<servername>\<instancename>>
$sql_server.databases| Format-Table -autosize Name,@{
Label= “% Used”
Expression={[math]::round((($_.spaceavailable/1kb)/$_.size),2)}
}Name % Used
-AdventureWorks2008R2 0.02
AdventureWorksDW2008R2 0
AdventureWorksLT2008R2 0.02
bigpubs2008 0.18
Customer 0.74
master 0.24
model 0.39
msdb 0.02
my_database 0.38
tempdb 0.8
Using the Format-Table cmdlet, you can easily and quickly create all kinds of reports Some
capabilities we haven’t discussed yet were used to create this report:
Calculated properties—The values displayed by Format-Table can be calculated
using scriptblocks That allows the logic to be highly customized These scriptblocks
are laid out as follows:
@{Label=”some text value”
Expression={the scriptblock to evaluate here}
}
Direct access to the NET Framework—The following line is directly from the
.NET Framework:
”[math]::round(value,decimal)”
.NET functionality is being used to round out the numbers to the second decimal
point
PowerShell has special meaning for 1kb, 1mb, 1gb and 1tb, which all present the
value of the counterpart in number of bytes—for example, 1kb=1024 The values can
also be uppercase
Trang 7Getting Table Properties
Another common task is to get a row count of the tables in a particular database:
PS SQLSERVER:\SQL\<servername>\<instancename>\Databases\
AdventureWorks2008R2\Tables> Get-ChildItem | Sort-Object
-descending|Select-Object -First 10| Format-Table -autosize Name,RowCountNote
NOTE
An easy-to-remember alias for Get-ChildItem is basically dir
In the preceding example using the AdventureWorks2008R2 database, the top 10 tables
with the highest row count value are returned
NOTE
The preceding example shows how many features are packaged within PowerShell,
which applies not only to SQL tables, but also to all NET objects Simply using
Get-Item on a particular table returns only the default properties of Schema, Name, and
Created Piping something like Get-Item [table_name] to either Format-Table * or
Get-Member exposes all the properties available for a particular object
Cmdlet Example: Invoke-SqlCmd
The Invoke-SqlCmd cmdlet was mentioned earlier It will likely be the most commonly
used cmdlet currently provided Here is a simple example using this cmdlet:
Invoke-sqlcmd -query “exec sp_help”
Using Invoke-SqlCmd, you can simply pass any T-SQL–based query as a value to the
cmdlet The preceding basic example is provided by running a basic built-in stored
proce-dure: sp_help
This example demonstrates several important issues, especially how powerful the provider
can be Based on the location in the SQL provider, some of the values passed to the
cmdlet are automatically provided to the cmdlet by the provider itself: the server and
database to query aren’t required in the command line
Let’s consider this example a bit further and do a few extra things with it
First, this cmdlet can accept input from the pipeline:
”exec sp_help”|ForEach-Object{Invoke-SqlCmd $_}
The preceding line demonstrates a few more issues that have already been discussed: the
ForEach-Object cmdlet, the special variable $_, and also the way parameters can
Trang 8ically match values to parameters even when the parameter name isn’t explicitly added to
the command entered
The sp_help stored procedure provides a lot of information What if only the extended
stored procedures were required?
When Get-Member is used, the members from this particular query are inspected, and it is
determined that the Object_type property is the value that indicates what kind of stored
procedure is being dealt with
The query to get only extended stored procedures is now the following:
”exec sp_help”|ForEach-Object{Invoke-SqlCmd $_}| `
Where{$_.Object_type -eq “extended stored proc”}|Select Name
Finally, the output consists only of extended stored procedures
Cmdlet Example: Invoke-PolicyEvaluation
Another one of the provided cmdlets is Invoke-PolicyEvaluation This cmdlet is used to
specify a SQL Server Policy-Based Management policy (or policies) that will be evaluated
against the target server You can easily cycle through all the available policies and
evalu-ate each one, or simply provide a list of policies to evaluevalu-ate separevalu-ated by a comma
Consider this example:
sl “C:\Program Files\Microsoft SQL Server\100\Tools\Policies\DatabaseEngine\1033”
Invoke-PolicyEvaluation -Policy “Database Auto Shrink.xml” -TargetServerName
“MSSQLSERVER”
The preceding command returns the output to the console of the result of the policy
eval-uation By default, the particular policy passed to the cmdlet is only checked In other
words, by default, properties are actually changed so that they are now compliant with the
policy
Joining Columns
Quite often, databases provide a table for users Frequently, these users have their last
name and first name in separate columns Because these are typically simple strings, a
feature, already discussed, allows two strings to be easily joined together
The following code snippet shows how two columns from the AdventureWorks2008R2
database are easily joined together from within the SQL minishell:
PS SQLSERVER:\SQL\D830\DEFAULT\databases\adventureworks2008r2> Invoke-SqlCmd
“Select * from Person.Person”| `
>> Select-Object -First 10|ForEach-Object{$_.LastName + “, “ + $_.FirstName}
Sánchez, Ken
Duffy, Terri
Tamburello, Roberto
Walters, Rob
Trang 9Erickson, Gail
Goldberg, Jossef
Miller, Dylan
Margheim, Diane
Matthew, Gigi
Raheem, Michael
Here, the first 10 records are selected, and then the LastName and FirstName values are
combined together
Retrieving an Entry
On occasion, you might need to get a particular entry from a table When the following
code snippet is run, an array is automatically returned:
PS SQLSERVER:\SQL\D830\DEFAULT\databases\adventureworks2008r2> Invoke-SqlCmd
“Select * from Person.Person”
PowerShell provides a simple way to look at particular elements within an array In the
following example, entry 100 is returned and then entries 95 to 105:
PS SQLSERVER:\SQL\D830\DEFAULT\databases\adventureworks2008r2> (Invoke-SqlCmd
“Select * from Person.Person”)[100]
PS SQLSERVER:\SQL\D830\DEFAULT\databases\adventureworks2008r2> (Invoke-SqlCmd
“Select * from Person.Person”)[95 105]
NOTE
The first element of an array is the element zero; therefore, the first record in an array
is retrieved by referencing the element id [0]
Summary
This chapter provides an overview of PowerShell and how it has been specifically
imple-mented in SQL Server 2008 Microsoft is putting a lot of effort into integrating PowerShell
into all its server-based products, including SQL Server Support for PowerShell in SQL
Server 2008 still has a way to go before it could ever be considered the main scripting
language, but the functionality available now is worth looking at
The next chapter delves into high availability and the options available in SQL Server 2008
Trang 10SQL Server High
Availability
What’s New in High Availability144
What Is High Availability?145
The Fundamentals of HA147
Building Solutions with One or More HA Options150
Other HA Techniques That Yield Great Results159
High Availability from the Windows Server Family Side162
With SQL Server 2008, Microsoft continues to push the
high availability (HA) bar higher and higher Extensive
high-availability options, coupled with a variety of
Windows server family enhancements, provide almost
everyone with a chance at achieving the mythical
“five-nines” (that is, 99.999% uptime)
Understanding your high-availability requirements is only
the first step in implementing a successful high-availability
application Knowing what technical options exist is
equally as important Then, by following a few basic design
guidelines, you can match your requirements to the best
high-availability technical solution
This chapter introduces a variety of fundamental HA
options—such as redundant hardware configurations, RAID,
and MSCS clustering—as well as more high-level options—
such as SQL clustering, data replication, and database
mirroring—that should lead you to a solid high-availability
foundation Microsoft has slowly been moving in the
direc-tion of trying to make SQL Server (and the Windows
oper-ating systems) as continuously available as possible for as
many of its options as possible Remember that Microsoft is
competing with the UNIX/Linux-based worlds that have
offered (and achieved) much higher uptime levels for years
The SQL Server RDBMS engine itself and the surrounding
services, such as Analysis Services, Integration Services,
Notification Services, and Reporting Services, have all taken
big steps toward higher availability