逐步 SQL 镜像 ASPState 数据库






4.80/5 (12投票s)
SQL 镜像变得容易 - 设置数据库镜像。
引言
本文将介绍
- 在镜像环境中设置 ASPState 数据库
- 配置 ASP.NET Web 应用程序以使用镜像的 ASPState 数据库
- 如何执行手动故障转移(用于维护场景)
- 如何执行强制故障转移(当数据库服务器意外崩溃时)
背景
企业为 SQL Server 数据库提供高可用性是相当普遍的需求,其中一种选择是在不同服务器上设置两个 SQL Server 数据库并通过 SQL Server 数据库进行镜像。Microsoft 在 SQL Server 2005 和 SQL Server 2008 中提供了开箱即用的镜像功能,它比群集/故障转移方案便宜得多,但仍能提供一定的保护。在镜像中,始终有一个主数据库(Principal)负责处理请求,一个镜像数据库(Mirror)则始终保持同步。如果主数据库发生故障,镜像数据库可以被强制切换为主数据库,并开始处理请求。一旦原来的主数据库恢复可用,它将成为新的镜像数据库。
设置镜像数据库并不像应该的那么直接。尽管有向导,但在数据库可以被镜像之前,还需要执行许多步骤,并且还有一些“陷阱”会阻止其正常工作。我曾为此花费了数天时间,经历了无数的痛苦和沮丧。尽管 Microsoft 提供了大量的相关文档,但其中很多可能并不相关,而且很难弄清楚究竟需要做什么。我需要一个设置基本镜像数据库的分步指南,但找不到,所以这是我为帮助其他人而提供的尝试。
我将使用 ASP 会话数据库作为示例,因为它是一个常见需求,但本指南适用于您拥有的任何数据库。我已将相同的步骤用于其他公司数据库。此指南也适用于 SQL Server 2005,尽管我是在 SQL Server 2008 标准版上执行这些步骤的。
一旦引入了镜像数据库服务器,ASP 会话就不能再使用状态服务器(State Server)或内存模型(In-Memory Model),而必须配置为使用 ASPState SQL Server 状态数据库。由于此数据库被镜像,用户可以在会话期间从一个 Web 服务器迁移到另一个服务器,并且会话状态将在服务器之间保持。
步骤 1 - 安装 ASP 会话数据库
对于普通数据库,此步骤被省略。
首先,我们需要在主服务器上安装 ASPState 数据库。
导航到 C:\Windows\Microsoft.NET\Framework\v2.0.50727 文件夹,然后键入以下命令
aspnet_regsql.exe -ssadd -sstype:p -S [myserver] -U [mylogin] -P [mypassword]
参数是区分大小写的。这将会在指定的服务器上创建 ASPState 数据库。您可以使用 -E 参数代替 -U 和 -P 参数,以使用当前凭据。
如果未指定 -sstype:p 参数,那么默认情况下,ASP.NET 会话将被放入 TempDB 数据库而不是 ASPState 数据库。这让我困惑了很长时间。对于正常的非镜像环境来说,这没问题,因为 ASP 会话会在服务器重启后被清除。但对于镜像环境来说,这就不行了,因为我们想要镜像的是 ASP 会话数据本身,而不仅仅是存储过程!此外,TempDB 数据库不支持镜像。-sstype:p 参数会使 ASP.NET 将会话表安装到 ASPState 数据库中,并且在服务器重启后会进行持久化。这正是我们想要用于镜像环境的行为。

步骤 2 - 在镜像服务器上安装数据库
对于普通数据库,从这一步开始。
为了将数据库传输到镜像服务器,我们需要在主服务器上执行 ASPState(或您要镜像的数据库)的**完整备份**,然后进行事务日志备份。
- 在主服务器上执行数据库的完整备份。
- 在主服务器上执行事务日志备份。
- 将备份文件复制到镜像服务器。
- 重要提示:在新的恢复步骤中执行完整备份的恢复,但在执行恢复之前,请转到“选项”,并确保选中“不恢复”(No Recovery)选项!这至关重要!
- 执行另一次**事务日志恢复**,同样使用“不恢复”(No Recovery)选项。(这很重要,否则在启动镜像时会收到错误 - 参见“陷阱”部分获取解释)。
您会注意到镜像服务器上的数据库现在标记为“正在恢复...”并且无法访问。这是正常且符合预期的!这让我困惑了相当长一段时间,以为是错误的。

镜像数据库始终处于永久恢复状态,以防止用户访问数据库,但会接收同步数据。如果数据库故障转移到镜像服务器,它将成为一个活动数据库,而旧的主数据库将进入恢复状态。
步骤 3 - 设置 SQL Server 服务模拟
默认情况下,在大多数安装中,服务应用程序中的 SQL Server 服务以本地系统帐户运行。然而,为了使镜像工作,需要将其更改为本地用户。本地系统帐户无法访问网络资源,因此无法通过终结点与镜像服务器通信。完成此步骤至关重要,因为我曾花了很多时间想知道为什么镜像不起作用。
- 在主服务器和镜像服务器上都创建一个具有相同用户名和密码的本地用户。例如,“sqluser”。
- 编辑 SQL Server 服务,并将其登录更改为此用户。
- 对 SQL Server Agent 服务执行相同的操作。
- 将 SQL Server Agent 服务更改为“自动”。
- 重新启动 SQL Server 服务,然后重新启动 SQL Agent 服务。
- 在主服务器和镜像服务器上都执行此操作!
SQL Agent 也必须运行。因为
- 它运行自动备份作业,并且
- 它会使 ASP 中的会话过期
如果您发现 ASPState 数据库中的**ASP.NET 会话未过期**,那是因为 SQL Agent 服务未运行。
有时,您可能会发现**SQL Agent 无法启动**。可以通过重新启动 SQL Server 服务,然后再次重新启动 SQL Agent 来解决此问题。
为您创建的用户在两个 SQL Server 上创建一个 SQL 登录。

步骤 4 - 设置镜像
现在,是时候实际设置镜像了!转到 ASPState 数据库(或您的数据库)的数据库属性,然后选择“镜像”选项卡。
如果在 SQL Server 2008 中**未显示“镜像”选项卡**,请重新运行安装程序,并确保您已勾选“完整 SQL 工具”选项。
- 点击“配置安全性”。
- 在向导中点击“下一步”。
- 选择您是否需要见证服务器(本文不涵盖见证服务器),然后点击“下一步”。
- 在“主服务器实例”阶段,将所有内容保留为默认值(您也无法更改任何内容)。
在“镜像服务器实例”阶段,从下拉列表中选择您的镜像服务器,然后点击“连接”以提供凭据。点击“下一步”。

- 在关于服务帐户的下一个对话框中,将它们留空(仅当服务器在域中或受信任的域中时才需要填写)。
- 点击“下一步”和“完成”。
- 点击“不启动镜像”。
- 如果需要,请输入服务器的 FQDN,但这并非必需(只要它可以解析即可)。
- 点击“启动镜像”(如果您没有输入 FQDN,将会出现一个警告,但您可以忽略它)。
- 镜像应该会启动,并在片刻之后,状态应为“已同步:数据库已完全同步”。
这样,您现在应该拥有一个工作的镜像了!执行一次手动故障转移进行测试。请参阅下面的“执行手动故障转移”说明。
以下是主服务器上一个工作的镜像设置的样子。

以下是镜像服务器上一个工作的镜像设置的样子。

执行手动故障转移
如果您需要进行维护而将某个服务器下线,您可以执行手动故障转移。有两种方法:使用 SQL Enterprise Manager 和使用 T-SQL。我将在此处解释这两种方法,您可以根据您的具体情况选择。
使用 SQL Enterprise Manager
在主服务器上,右键单击数据库,选择“镜像”。然后,您将看到一个“故障转移”(Failover)按钮。点击它,您将收到一条关于故障转移将交换角色的消息。点击“是”,大约 10 秒后,角色就会交换。如果您刷新两个服务器上的数据库,您将看到主服务器现在标记为“正在恢复...”而旧的镜像服务器已成为新的主服务器。
使用 T-SQL
以下是执行与上面相同操作的 T-SQL。如果您的镜像使用同步模式,则可以忽略 SET SAFETY
行。您可以在“镜像属性”(右键单击数据库,选择“镜像”)中查看正在使用的模式。
--Run on principal
USE master
GO
ALTER DATABASE dbName SET SAFETY FULL
GO
ALTER DATABASE dbName SET PARTNER FAILOVER
GO
--Run on new principal
USE master
GO
ALTER DATABASE dbName SET SAFETY OFF
GO
执行强制故障转移
如果您的主服务器发生故障(Boom!)并且出现意外停机,那么您需要执行强制故障转移。这意味着强制镜像服务器成为主服务器。此操作存在轻微的数据丢失风险,但如果主服务器已宕机,您还有其他选择吗?显然,您只应在主服务器意外不可用时执行此强制故障转移。在所有其他情况下,您应该执行正常的手动故障转移。
使用 T-SQL 执行强制故障转移
--Run on mirror if principal isn't available
USE
master
GO
ALTER DATABASE dbName SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS
GO
例如,在生产环境中,您将有一个监控系统,该系统会定期检查主服务器的可用性。如果它检测到数据库不可用,则可以运行 VBScript 或 USQL 命令行在镜像数据库上执行此 T-SQL。如果您有见证服务器,则会自动完成此操作。
步骤 5 - 配置 ASP.NET 应用程序使用镜像数据库
最后一步是配置您的 ASP.NET 应用程序以使用镜像的 ASPState SQL Server 数据库(或您的数据库)。如果您使用的是 .NET 2.0 或更高版本,请按照以下步骤操作:
- 在 web.config 文件中,将任何现有的
<sessionState
键更改为以下内容(或者如果不存在,则添加它):
<sessionState mode="SQLServer" allowCustomSqlDatabase="true" sqlConnectionString="data source=[PRINCIPALSERVER]; failover partner=[MIRRORSERVER];initial catalog=ASPState;user id=[DBUSER]; password=[DBPWD];network=dbmssocn;" cookieless="false" timeout="180" />
data source = [PRINCIPALSERVER]
- 对于 data source,添加主服务器的 IP 地址或名称。这是一个**必需**参数。failover partner = [MIRRORPARTNER]
- 指定镜像服务器的名称。这是一个**必需**参数。initial catalog = ASPState
- 或者,如果您使用的是自定义数据库,则指定您的数据库名称。这是一个**必需**参数。allowCustomSqlDatabase = "true"
- 这是一个**必需**参数。
通过将您的应用程序配置为使用这些设置,当应用程序向数据库发出请求且主服务器不可用时,.NET 将自动将请求发送到镜像服务器。这应该是透明的,因此您的网站用户应该不会注意到任何中断。
如果您使用的是 .NET 1.1,则没有 Failover Partner,因此您需要自己编写代码来转移客户端。这可以是一个简单的 try...catch
块,用于数据库连接,在 catch
块中,它会尝试使用镜像服务器重试。
在意外停机的情况下,会发生以下情况:
- 主服务器宕机。
- 见证服务器或您的监控服务检测到主数据库不可用。
- 见证服务器或您的监控服务强制故障转移到您的镜像服务器,镜像服务器成为新的主服务器。
- ADO.NET 检测到主服务器已宕机,并自动重试连接镜像服务器。
重要提示:如果您有两个或更多 Web 服务器,则需要在每个 Web 服务器上复制上述 SessionState
条目。
您还需要确保每个 Web 服务器上都有**相同**的验证密钥/解密密钥。否则,如果在不同服务器上创建的会话数据将无法读取。如果镜像 ASPState 数据库,这是必需的。
<machineKey
validationKey="D581FCFD1xxxxxxxxxxxxxx16FEEBB4C56Axxxxxxxxxxxxxxxxxxxxxxxxxx"
decryptionKey="55B44F83Cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
validation="SHA1" decryption="AES"
/>
注意事项
在处理镜像时,您可能会遇到以下错误消息和陷阱。
尝试使用 SET PARTNER FORCE_SERVICE_ALLOW_DATA_LOSS T-SQL 执行强制故障转移时,会收到以下错误:
"Cannot alter database <db>because the database is not in the correct state
to become the principal"
您可以正常执行手动故障转移,但强制故障转移会导致错误。如果镜像检测到主服务器仍在运行,它将**不会**切换为主服务器。如果您使用代码或脚本测试强制故障转移,而没有停止主服务器上的 SQL 实例,则可能会发生这种情况。如果停止主服务器上的服务,则可以执行强制故障转移。
在设置镜像时,尝试启动镜像时会收到以下错误消息:
"Remote copy of <db>has not been rolled forward to a point in time
that is encompassed in the local copy of the database. Error: 1402"
如果您未在主服务器上执行事务日志备份并将其(不恢复)恢复到镜像服务器,则会出现此错误。您**必须**执行此步骤,否则会发生此错误。
镜像第二个数据库
如果您想在同一服务器上镜像多个数据库,这是可能的。您需要为下一个数据库重复步骤 2,然后重复步骤 4(只需点击下一步、下一步、完成等)。这些数据库将使用相同的终结点端口。
停止镜像
如果您想停止并删除数据库的镜像,请按照以下步骤操作:
在主服务器上
- 右键单击,选择“镜像”>“删除镜像”。
- 刷新数据库视图(主服务器现在应显示为普通数据库)。
此时数据库已成为普通数据库。 - 删除数据库。
在镜像服务器本身上
- 目前会显示“正在恢复...”
- 右键单击并删除数据库,或将其脱机然后删除。
如果“删除”选项不可用,或者您没有控制权,请刷新数据库视图或重新打开 SQL Enterprise Manager。
或者,要将其恢复为普通数据库而不是删除:执行另一次数据库恢复,但将选项更改为“带恢复”(With Recovery)(顶部选项)。
结论
如果您遵循了本文的步骤,您现在应该已成功地将 ASPState 数据库(或您自己的数据库)设置为镜像数据库,从而为您的 Web 用户提供了相当好的可用性和防故障能力。
希望本文对您有所帮助。如有任何问题,请在评论区留言,我会尽量回答,或在必要时更新文章使其更清晰。感谢阅读!
注释
您可以在同一组服务器上镜像多个数据库。但是,当然,越多,性能越差。
历史
- 2008 年 12 月 1 日:版本 1.0
- 首次发布
- 2008 年 12 月 19 日:版本 1.1
- 添加了“陷阱”、“镜像第二个数据库”和“停止镜像”部分。