之前有写过一篇:SQL Server 镜像证书过期处理 这是之前为替换证书做的测试准备,介绍了如何替换过期的镜像证书。而这篇文章则是对昨天的工作中进行了大量服务器的证书替换的时候碰到了一些问题,这里进行分析和总结。
下面是在生产中操作的使用脚本:
--脚本1
select name, expiry_date from sys.certificates where issuer_name not like \'MS_%\'
go
declare @sql varchar(max)
set @sql = \'\'
select top 1 @sql = @sql + \'use master\' + CHAR(10) +
+\'alter database \'+(select top 1 name from sys.databases where database_id > 4)+\' set partner suspend\' + CHAR(10) +
+\'create certificate \'+name+\'_new with subject = \'\'mirror\'\',start_date=\'\'2012-01-01\'\', expiry_date=\'\'2099-06-01\'\';\' + CHAR(10) +
+\'alter endpoint endpoint_mirroring\' + CHAR(10) +
+\'for database_mirroring (authentication = certificate \'+name+\'_new)\' + CHAR(10) +
+\'drop certificate \'+name+\'\' + CHAR(10) +
+\'backup certificate \'+name+\'_new to file = \'\'d:\certificate\\'+name+\'_new.cer\'\';\' + CHAR(10) +
+\'/*****************************************************/\' + CHAR(10)
from sys.certificates
where issuer_name not like \'MS_%\' and pvt_key_encryption_type = \'MK\'
print(@sql)
--exec(@sql)
go
select name, expiry_date from sys.certificates where issuer_name not like \'MS_%\'
select database_id, mirroring_state_desc from sys.database_mirroring
--脚本2
select name, expiry_date from sys.certificates where issuer_name not like \'MS_%\'
select database_id, mirroring_state_desc from sys.database_mirroring where mirroring_state_desc is not null
go
declare @sql varchar(max)
set @sql = \'\'
select top 1 @sql = @sql
+\'create certificate \'+a.name+\'_new AUTHORIZATION \'+b.name+\' from file = \'\'D:\certificate\\'+a.name+\'_new.cer\'\';\' + CHAR(10) +
+\'drop certificate \'+a.name + CHAR(10) +
+\'WAITFOR DELAY \'\'00:00:05\'\'\' + CHAR(10) +
+\'alter database \'+(select top 1 name from sys.databases where database_id > 4)+\' set partner resume\' + CHAR(10) +
+\'/*****************************************************/\' + CHAR(10)
from sys.certificates a
inner join sys.database_principals b on b.principal_id = a.principal_id
where issuer_name not like \'MS_%\' and pvt_key_encryption_type = \'NA\'
print (@sql)
--exec(@sql)
go
select name, expiry_date from sys.certificates where issuer_name not like \'MS_%\'
select database_id, mirroring_state_desc from sys.database_mirroring where mirroring_state_desc is not null
这个脚本可以同在主机和镜像机器上跑,但是对于alter database语句的话只允许在一台机器上执行。其中有两个@sql变量的定义,说明这段脚本是分成两次跑的。exec语句被我注释掉防止误操作。镜像机的print脚本结果如下:
use master
alter database DNMembership set partner suspend
create certificate wha999m_new_new with subject = \'mirror\',start_date=\'2012-01-01\', expiry_date=\'2099-06-01\';
alter endpoint endpoint_mirroring
for database_mirroring (authentication = certificate wha999m_new_new)
drop certificate wha999m_new
backup certificate wha999m_new_new to file = \'d:\certificate\wha999m_new_new.cer\';
/*****************************************************/
create certificate wha999_new_new AUTHORIZATION wha999_user from file = \'D:\certificate\wha999_new_new.cer\';
drop certificate wha999_new
WAITFOR DELAY \'00:00:05\'
alter database DNMembership set partner resume
/*****************************************************/
详细的操作步骤:
- 在镜像机上执行第一段脚本:暂停数据库镜像、创建新证书、修改镜像端点、删除镜像机老证书、备份证书(用于主机还原)
- 在主机上执行所有脚本:前半部分操作同上,后半部分进行镜像机证书的还原
- 在镜像机上执行第二段脚本:还原主机的证书、删除主机老证书、等待5秒有还原数据库镜像(比较进行几秒钟的等待否则数据库镜像恢复会报错)
注:操作删除证书和修改端点前一定要把镜像暂停否则有可能导致镜像失效
上述操作才特殊情况下可能碰到的问题:
在新证书创建后就立即把老证书删除掉,如果在这个过程中出现证书丢失或者操作错误导致重复跑了两次脚本的情况下会很悲剧。所以建议可以在镜像重新恢复后确定没有问题再进行老证书的删除。