使用Powershell脚本做SQL Server镜像切换。
1、打开脚本,确认本地IP地址,与浮动VIP地址配置正确。
2、执行以下脚本。将在主服务器上卸载VIP。并开始做数据库的切换。
[string] $global:virtual_ip = '192.168.223.155'
[string] $global:local_ip = '192.168.223.151'
[string] $global:backup_virtual_ip = '169.254.117.21'
[string] $global:backup_local_ip = '169.254.117.22'
[string] $global:port = '1433'
[Boolean] $global:can_failover = $false
function get_all_ipaddrs {
PROCESS {
return Get-NetIPAddress
}
}
function get_ipaddr_info
{
param (
$addrs,
$ip
)
PROCESS {
foreach($cur_ip in $addrs) {
if ($cur_ip.IPAddress -eq $ip) {
return $cur_ip
}
}
return $false
}
}
function unmount_vip {
PROCESS {
$ip_addrs = get_all_ipaddrs
$vip = get_ipaddr_info -ip $global:virtual_ip -addrs $ip_addrs
if ($vip -ne $false) {
Remove-NetIPAddress -IPAddress $global:virtual_ip
}
$global:can_failover = $true
Write-Output('正在卸载浮动IP: {0}' -f $global:virtual_ip)
Write-Output('Can Failover: {0}' -f $global:can_failover)
$bvip = get_ipaddr_info -ip $global:backup_virtual_ip -addrs $ip_addrs
if ($bvip -ne $false) {
Remove-NetIPAddress -IPAddress $global:backup_virtual_ip
}
Write-Output('正在卸载备份浮动IP: {0}' -f $global:backup_virtual_ip)
}
}
function execute_sql {
param (
[string] $t_sql
)
PROCESS {
return Invoke-Sqlcmd -Database 'master' -ServerInstance ($global:local_ip + ',' + $global:port) -Query $t_sql
}
}
function get_databases {
[string] $t_sql = '
SELECT DB_NAME(database_id) AS name
FROM sys.database_mirroring
WHERE mirroring_state = 4
AND mirroring_role = 1
ORDER BY name
'
return execute_sql -t_sql $t_sql
}
function check_database_mirroring {
[string] $t_sql = '
SELECT DB_NAME(database_id) AS name,
mirroring_state_desc
FROM sys.database_mirroring
WHERE mirroring_state <> 4
'
return execute_sql -t_sql $t_sql
}
function failover {
param (
$db
)
PROCESS {
$sql_mode = 'ALTER DATABASE [{0}] SET PARTNER FAILOVER'
$t_sql = $sql_mode -f $db
$result = execute_sql -t_sql $t_sql
return $result
}
}
function safety_full {
param (
$db
)
PROCESS {
$sql_mode = 'ALTER DATABASE [{0}] SET PARTNER SAFETY FULL'
$t_sql = $sql_mode -f $db
Execute_sql -t_sql $t_sql
}
}
function failover_all_dbs {
PROCESS {
$databases = get_databases
foreach($db in $databases) {
Write-Output('[{0}] 开始切换' -f $db.name)
safety_full -db $db.name
failover -db $db.name
Write-Output('[{0}] 切换完成' -f $db.name)
}
Write-Output('所有数据库切换完成')
}
}
function main {
PROCESS {
$checked = check_database_mirroring
if ($checked) {
Write-Output('请检查以下数据库的同步状态是否正常')
foreach($db in $checked) {
Write-Output('Database: {0} | Mirroring_Satae:{1}' -f $db.name, $db.mirroring_state_desc)
}
return $false
}
unmount_vip
$all_ips = get_all_ipaddrs
$all_ips
if ($global:can_failover -eq $true) {
failover_all_dbs
}
}
}
main
3、在备机上挂载IP
[string] $global:virtual_ip = '192.168.223.155'
[string] $global:local_ip = '192.168.223.151'
[string] $global:backup_virtual_ip = '169.254.117.21'
[string] $global:backup_local_ip = '169.254.117.22'
[Object] $global:all_addrs
function get_all_ipaddrs {
PROCESS {
return Get-NetIPAddress
}
}
function get_ipaddr_info {
param (
$ip
)
PROCESS {
foreach($cur_ip in $global:all_addrs) {
if ($cur_ip.IPAddress -eq $ip) {
return $cur_ip
}
}
return $false
}
}
function mount_vip {
param (
$addr,
$local_ip
)
PROCESS {
if (Test-Connection -ComputerName $addr -Count 1 -Delay 1)
{
Write-Output('')
}
New-NetIPAddress -IPAddress $addr -InterfaceIndex $local_ip.InterfaceIndex -PrefixLength $local_ip.PrefixLength -AddressFamily $local_ip.AddressFamily
}
}
function main {
PROCESS {
$global:all_addrs = get_all_ipaddrs
$local_ip = get_ipaddr_info -ip $global:local_ip
if ($local_ip -ne $false) {
mount_vip -addr $global:virtual_ip -local_ip $local_ip
}
else {
Write-Output('浮动IP:{0}未能挂载成功,请检查本地IP:{1}是否配置正确' -f $global:virtual_ip, $global:local_ip)
}
$backup_local_ip = get_ipaddr_info -ip $global:backup_local_ip
if ($backup_local_ip -ne $false) {
mount_vip -addr $global:backup_virtual_ip -local_ip $backup_local_ip
}
else {
Write-Output('备份浮动IP:{0}未能挂载成功,请检查本地IP:{1}是否配置正确' -f $global:backup_virtual_ip, $global:backup_local_ip)
}
$global:all_addrs = get_all_ipaddrs
$global:all_addrs
}
}
main