functions/Test-DBReadOnlyRouting.ps1
function Test-DBReadOnlyRouting { <# .SYNOPSIS Tests read only routing for an availability group, and returns whether or not the routing is valid. .DESCRIPTION Tests read only routing for an availability group, and returns whether or not the routing is valid. .PARAMETER ServerInstances The sql server instances to connect to. This should be the listener name of the AG group. .PARAMETER Database The database. This database must be a synchronized database. If left empty, the the script will attempt to discover a synchronized database. .PARAMETER Credentials Specifies credentials to connect to the database with. If not supplied then a trusted connection will be used. This authentication will be used for each server. .OUTPUTS .EXAMPLE PS >Test-DBReadOnlyRouting -ServerInstances "listener1", "listener2" | format-table .LINK https://github.com/tcartwright/tcdbtools .NOTES Author: Tim Cartwright #> Param ( [Parameter(Mandatory=$true)] [string[]]$ServerInstances, [string]$Database, [pscredential]$Credentials ) begin { $ret = New-Object System.Collections.ArrayList } process { foreach ($ServerInstance in $ServerInstances) { try { $serverTest = [PSCustomObject] @{ ListenerName = $ServerInstance Database = $null ReadOnlyServer = $null ReadWriteServer = $null ReadOnlyIsValid = $false Reason = $null } $ret.Add($serverTest) | Out-Null $connection = New-DBSQLConnection -ServerInstance $ServerInstance -Database "master" -Credentials $Credentials $connectionRO = New-DBSQLConnection -ServerInstance $ServerInstance -Database "master" -Credentials $Credentials -ApplicationIntent ReadOnly $connection.Open() if (-not $Database) { $sql = (GetSQLFileContent -fileName "FindSynchronizedDB.sql") -f $Database $Database = Invoke-DBScalarQuery -conn $connection -sql $sql } else { # doing this to block sql injection for the USE statement below. ensure their db name actually exists and to also ensure it is synchronized $sql = "SELECT d.[name] FROM sys.databases d WHERE d.[name] = @name" $parameters = @( (New-DBSqlParameter -name "@name" -type NVarChar -size 256 -value $Database) ) $Database = Invoke-DBScalarQuery -conn $connection -sql $sql -parameters $parameters } if ($Database) { $connectionRO.Open() $query = "USE [$Database]; SELECT @@SERVERNAME;" Write-Information "TESTING Read Only Routing for: `r`n`tSERVER: $($ServerInstance.ToUpper())`r`n`tDATABASE: $($Database.ToUpper())`r`n" Write-Information "Connecting using RW connection" $server = (Invoke-DBScalarQuery -conn $connection -sql $query) Write-Information "Connecting using RO connection" $serverRO = (Invoke-DBScalarQuery -conn $connectionRO -sql $query) $serverTest.ReadOnlyServer = $serverRO $serverTest.ReadWriteServer = $server $serverTest.ReadOnlyIsValid = $serverRO -ine $server $serverTest.Database = $Database if (-not $serverTest.ReadOnlyIsValid) { $serverTest.Reason = "SERVERS ARE EQUAL" } } else { $serverTest.Reason = "NO SYNCHRONIZED DBS" } } catch { $serverTest.Reason = "EXCEPTION: $($_.Exception.GetBaseException().Message)" } finally { if ($connection) { $connection.Dispose() } if ($connectionRO) { $connectionRO.Dispose() } } } } end { return $ret } } |