镜像会话中主服务器的扩容
某一个镜像会话中的主库所在服务器磁盘容量不足了,现要新添加一个磁盘分区用于扩容。通常的做法是:加完分区后,添加新数据文件(或者新文件组)到新分区,之后再重做镜像。
如果此库比较大,则重做镜像会是件耗时和拖累性能的事情。会不会有更好的方法呢?在实际操作中,我以”数据库文件布局方式”分为三种情况:
1. 主库和镜像库的文件布局一样,而且新增加分区盘符在两台机上都存在。
“一样”指mdf/ndf和ldf文件目录地址相同。在创建镜像时,还原数据库未指定“MOVE”则会一样。
如主库包含C:\DB_Test\Mirror_test_data.mdf和C:\DB_Test\Mirror_test_log.ldf,则镜像库的文件目录地址也是这样。
主机新加的分区为D,新增数据文件或文件组一样指向D:\NewFile。镜像机上也要有D分区。模拟代码如下:
use master
go
CREATE DATABASE [Mirror_Test] ON PRIMARY
( NAME = N'Mirror_Test', FILENAME = N'C:\DB_Test\Mirror_test_data.mdf' , SIZE = 3072KB ,
MAXSIZE = 5120KB , FILEGROWTH = 1024KB )
LOG ON
( NAME = N'Mirror_Test_log', FILENAME = N'C:\DB_Test\Mirror_test_log.ldf' , SIZE = 5120KB ,
MAXSIZE = 10240KB , FILEGROWTH = 1024KB )
GO
use Mirror_Test
go
--每行占一页,方便快速填充满数据
create table tb1(id int not null,val char(8000));
go
set nocount on;
declare @i int=0,@val char(8000)='abc';
--不到1000行就会充满,然后报错
while (@i<1000)
begin
insert into tb1 values(@i,@val);
set @i=@i+1;
end
set nocount off;
go
创建并填充数据后,再配置镜像。
成功添加新分区D盘(两边都有)后,开始添加数据文件。在两台机上的D盘分别创建了D:\NewFile目录用于添加新文件。
<1.添加数据文件。成功添加,而且镜像会话正常。
alter database Mirror_Test
add file( NAME = N'Mirror_Test_data2', FILENAME = N'D:\NewFile\Mirror_test_data2.ndf' , SIZE = 3072KB ,
MAXSIZE = 5120KB , FILEGROWTH = 1024KB )
to filegroup [PRIMARY]
go
<2.添加文件组。成功添加,而且镜像会话正常。
alter database Mirror_Test add filegroup [NewFG]
go
alter database Mirror_Test
add file( NAME = N'Mirror_Test_data3', FILENAME = N'D:\NewFile\Mirror_test_data3.ndf' , SIZE = 3072KB ,
MAXSIZE = 5120KB , FILEGROWTH = 1024KB )
to filegroup [NewFG]
go
<3.添加日志文件。成功添加,而且镜像会话正常。
alter database Mirror_Test
add log file( NAME = N'Mirror_Test_log2', FILENAME = N'D:\NewFile\Mirror_test_log2.ldf' , SIZE = 1024KB ,
MAXSIZE = 5120KB , FILEGROWTH = 1024KB)
to filegroup [PRIMARY]
go
2. 主库和镜像库的文件布局不相同,而且新增加分区盘符在两台机上都存在。
顾名思义,文件目录地址不同。生产环境中,往往是这样的。
删除之前的镜像环境,主库的创建跟之前的一样,文件分布在C:\DB_Test。只是在创建镜像库时,用move选项将镜像库的文件还原到E:\DB_Test。
配置镜像后,主库文件:
镜像库文件:
主库服务器成功添加新分区D盘(两边都有)后,开始添加数据文件。在两台机上的D盘分别创建了D:\NewFile目录用于添加新文件。代码跟前面的一样。
<1.添加数据文件。成功添加,而且镜像会话正常。
<2.添加文件组。成功添加,而且镜像会话正常。
<3.添加日志文件。成功添加,而且镜像会话正常。
3. 主库和镜像库的文件布局不相同,而且新增加分区的盘符在镜像机上不存在。
这是生产环境上最复杂的情况。
创建镜像环境,主库文件指向C:\DB_Test,镜像库文件指向D:\DB_Test。在主库服务器上新增加磁盘分区E,而镜像服器上没有分区E。
主库新增加数据文件指向E:\NewFile,而镜像服务器新增数据文件将指向D:\NewFile.
<1.添加数据文件。
alter database Mirror_Test
add file( NAME = N'Mirror_Test_data2', FILENAME = N'E:\NewFile\Mirror_test_data2.ndf' , SIZE = 3072KB ,
MAXSIZE = 5120KB , FILEGROWTH = 1024KB )
to filegroup [PRIMARY]
go
执行添加后,报错并且数据文件没有添加到磁盘上:
消息 1833,级别 16,状态 2,第 1 行
只有执行了下一个 BACKUP LOG 操作后,才能再次使用文件 'Mirror_Test_data2'。
按提示备份主库的日志,拿到镜像库去还原。还原时要注意:因为镜像服务器没有E盘,所以还原时需要指定MOVE选项以还原到D:\NewFile.
restore log Mirror_Test
from disk=N'C:\DB_Test\MTL2.bak'
with norecovery, move 'Mirror_Test_data2' to 'D:\NewFile\DB_Test_data2.ndf'
go
仍然报错:
消息 3104,级别 16,状态 1,第 1 行
无法对数据库 'Mirror_Test' 运行 RESTORE,因为已将它配置用于数据库镜像。如果希望还原该数据库,则请使用 ALTER DATABASE 删除镜像。
也就是说,仍然要停掉镜像会话才能恢复日志。其实停掉后,也不能恢复日志。
正确的做法是:先停止镜像会话—>主库添加文件—>备份主库日志并在镜像库上还原—>重建镜像会话。
<2.添加文件组。
正确的做法是:先停止镜像会话—>主库添加文件—>备份主库日志并在镜像库上还原—>重建镜像会话。
<3.添加日志文件。
正确的做法是:先停止镜像会话—>主库添加文件—>备份主库日志并在镜像库上还原—>重建镜像会话。
总结
- 在第一种和第二种情况,新添加的文件或文件组的文件目录地址,必须要在镜像机上也存在一模一样的目录地址(盘符和层级目录一样)。
- 在新建镜像会话时,尽量保证镜像会话的两个库的文件目录地址一样。这样会给以后扩容带来方便。
- 如果是第三种情况,正确的做法是:先停止镜像会话-->主库添加文件/文件组-->备份主库日志并在镜像库上还原-->重建镜像会话。