【IT168 专稿】最近我接到公司的一个任务,需要在2010年一季度将部分生产数据库从SQL Server 2005升级到SQL Server 2008,由于公司的业务几乎不能容忍停机,每秒都有大量的资金流进流出,任何意外都可能造成严重的损失,意味着维护,升级和迁移操作必须非常快地完成,使业务几乎没有中断,我使用过SQL Server镜像作为迁移的手段,也使用过SQL Server镜像作为转移到新硬件的解决方案,SQL Server镜像也是升级到新版本的一个有效方法,在企业版和标准版中都含有镜像功能。
测试中的发现
SQL Server 2005 SP3企业版镜像到SQL Server 2008企业版没有问题,但有一个限制,那就是镜像时版本必须对应,如果你想将SQL Server 2005 SP3标准版镜像到SQL Server 2008企业版,那是不可能的。我测试了企业版到企业版的镜像,包括数据和对象的操作及创建,我还测试了异步镜像功能,所有测试都顺利通过了,我的测试环境如下图所示。
图1 测试环境
观察到的缺点
使用快照镜像时会受到限制。因为SQL Server 2005的数据库版本是611,SQL Server 2008的数据库版本是655,如果你不将其升级到655,就不能创建快照。
镜像是单向的。你不能将SQL Server 2008通过镜像恢复成SQL Server 2005,没有降级镜像的办法可用。
一旦开始升级,就无法停止,即当你输入:
你的数据库将会输出:
Database 'JUNK' running the upgrade step from version 611 to version 621.
Database 'JUNK' running the upgrade step from version 621 to version 622.
Database 'JUNK' running the upgrade step from version 622 to version 625.
???
Database 'JUNK' running the upgrade step from version 652 to version 653.
Database 'JUNK' running the upgrade step from version 653 to version 654.
Database 'JUNK' running the upgrade step from version 654 to version 655.
RESTORE DATABASE successfully processed 0 pages in 1.825 seconds (0.000 MB/sec).
一旦故障转移到新的镜像,就没有办法回到2008了,这意味着故障转移是最终性质的,唯一的办法是再次从2005镜像到2008。
我建议仅在宕机时间特别苛刻的环境下使用这种升级方法,在开始之前无论如何请做好数据库备份,代理作业和相关脚本的备份工作,根据我的经验,如果你花1个小时进行升级规划,那至少需要花5个小时来验证你的想法是否可行。
在SQL Server 2005实例上创建数据库,执行一次完整备份,然后备份一下事务日志,将最后的事务捕获下来,它将应用到镜像数据库上。
( NAME = N'NEEDTOUPGRADE', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\NEEDTOUPGRADE.mdf' , SIZE = 2048KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'NEEDTOUPGRADE_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\NEEDTOUPGRADE_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
--执行完整备份
--备份最近的事务日志
接下来使用一个最基本的端点配置,启动端点为镜像做好准备。
AUTHORIZATION [PMHC\tkrueger]
STATE=STARTED
AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL)
FOR DATA_MIRRORING (ROLE = PARTNER, AUTHENTICATION = WINDOWS NEGOTIATE
, ENCRYPTION = REQUIRED ALGORITHM RC4)
然后到SQL Server 2008数据库上,使用刚刚的完整备份还原数据库,接着应用备份的事务日志,完成后就可以启动数据库同步了。
--还原完整备份
FROM DISK = 'C:\NEEDTOUPGRADE_full_initial.bak'
WITH NORECOVERY,
MOVE 'NEEDTOUPGRADE' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\NEEDTOUPGRADE_mirror.mdf',
MOVE 'NEEDTOUPGRADE_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\NEEDTOUPGRADE_mirror_log.ldf'
,REPLACE,NORECOVERY
GO
--应用最近的事务日志
GO
现在SQL Server 2008上的数据库处于no recovery状态,我们可以通过端口5022的通信将其配置为镜像伙伴。
注意:我们的数据库版本现在仍然是611,SQL Server 2008的版本应该是655,我们将不能正常执行快照和其它与镜像相关的操作,我前面也提到了这是一个缺陷。
我们再在镜像(SQL Server 2008)上创建一个端点:
AUTHORIZATION [PMHC\tkrueger]
STATE=STARTED
AS TCP (LISTENER_PORT = 5023, LISTENER_IP = ALL)
FOR DATA_MIRRORING (ROLE = PARTNER, AUTHENTICATION = WINDOWS NEGOTIATE
, ENCRYPTION = REQUIRED ALGORITHM RC4)
现在配置数据库,使其成为一个伙伴。
当镜像准备好接受事务时,我们可以配置principle了。
回到我们的SQL Server 2005实例,现在我们可以告诉NEEDTOUPGRADE已经成为端口5023上的伙伴。
我们没有使用witness,在principle SQL Server 2005实例上,运行下面的命令关闭实例:
结束升级
为了完成升级,我们需要故障转移镜像,但这时会有个问题,当镜像失效时,SQL Server 2008将处于暂停模式,这是因为我们的镜像是单向的,简单说就是可以从2005到2008应用事务日志,但从2008到2005就不行,因此我们一直强调在故障转移之前先做备份,即使是处于暂停状态,镜像数据库的所有功能仍然有效,你可以验证应用程序,并允许用户重新登录。
清理
要移除镜像,在SQL Server 2008实例上运行:
移除镜像,清除升级镜像的配置信息,将数据库真正升级到655,但不用删除端点,你可以使用下面的命令验证数据库版本的变化:
接下来我们可以使用下面的命令将兼容级别设为100:
最后一步是修复NEEDTOUGPRADE数据库上可能存在的孤儿登录会话,这对于普通用户而言可能有点难度,如果你使用了SQL身份验证,可能还得重设密码,如果使用的是Windows身份验证,只需要完成孤儿登录会话,不需要修改密码,使用下面的脚步可以修复孤儿登录进程:
USE AdventureWorks
GO
DECLARE @loop INT
DECLARE @USER sysname
IF OBJECT_ID('tempdb..#Orphaned') IS NOT NULL
BEGIN
DROP TABLE #orphaned
END
CREATE TABLE #Orphaned (UserName sysname, UserSID VARBINARY(85),IDENT INT IDENTITY(1,1))
INSERT INTO #Orphaned
EXEC SP_CHANGE_USERS_LOGIN 'report';
IF(SELECT COUNT(*) FROM #Orphaned) > 0
BEGIN
SET @loop = 1
WHILE @loop <= (SELECT MAX(IDENT) FROM #Orphaned)
BEGIN
SET @USER = (SELECT UserName FROM #Orphaned WHERE IDENT = @loop)
IF(SELECT COUNT(*) FROM sys.server_principals WHERE [Name] = @USER) <= 0
BEGIN
EXEC SP_ADDLOGIN @USER,'password'
END
EXEC SP_CHANGE_USERS_LOGIN 'update_one',@USER,@USER
PRINT @USER + ' link to DB user reset';
SET @loop = @loop + 1
END
END
SET NOCOUNT OFF
上面谈到的所有这些步骤加起来可能需要5到10分钟的中断时间,如果你准备充分,时间还可以缩短。我的建议是在实施升级前预先告知用户,以便让他们做好升级准备,如果可以的话,最好将你的升级计划讲给大家听,不仅可以将他们觉得升级时间很短,而且还可以增强你们之间的关系。