使用SQL镜像和连接字符串实现自动故障转移

3
我有三个服务器用于设置SQL镜像和自动故障转移,使用见证服务器。这如预期一样工作。
现在我的应用程序连接数据库时,在发生故障转移时似乎存在问题——我需要手动干预并更改连接字符串才能重新连接。到目前为止,我找到的最佳解决方案涉及使用连接字符串的Failover Partner参数,但它既不直观也不完整:Data Source="Mirror";Failover Partner="Principal"。可以在这里找到更多信息。
从上面博客中的示例(方案#3)中可以看出,当第一次故障转移发生时,如果主要节点(故障转移伙伴)不可用,则将使用数据源(即新的主要节点)。如果它再次失败(我只尝试了一个有限的时间),则会出现错误消息。发生这种情况是因为连接字符串被缓存,因此除非此连接字符串已刷新,否则它将继续输出错误(似乎在遇到错误后连接字符串会在大约5分钟后刷新)。如果在故障转移后交换数据源和故障转移伙伴,则还会有一次平稳故障转移。
有没有一种方法可以实现对使用镜像数据库的应用程序的完全自动故障转移(无需看到错误)?
我可以看到使用自定义脚本的潜在解决方案,该脚本将轮询当前活动的数据库节点名称,并相应地调整连接字符串,但是目前似乎过于繁琐。

上面的链接已经失效了。对于任何正在寻找它的人,这个链接仍然有效:https://learn.microsoft.com/nl-nl/archive/blogs/spike/clarification-on-the-failover-partner-in-the-connectionstring-in-database-mirror-setup - Roeland
5个回答

3

1
那么为什么在关闭连接池的情况下它可以按预期工作呢? - Shagglez
当连接池开启时,与主服务器建立的连接会被保留以供将来使用,其中次要服务器(从服务器)也会与之一起存储。这些连接不会发生故障转移。如果关闭连接池,则每次都会创建一个新的连接并从配置文件中读取。由于无法连接到主服务器,因此它们将按照配置文件中的故障转移而非主服务器值进行工作。 - bennie j
更多详细信息请参见此处:http://blogs.msdn.com/b/spike/archive/2010/12/08/clarification-on-the-failover-partner-in-the-connectionstring-in-database-mirror-setup.aspx - bennie j
从第二个链接中:“...SQL Server将向客户端发送故障转移伙伴...”。在我的情况下,无论哪个服务器是主服务器,第一次故障转移都正常工作,但第二次就不行了。从这个情况来看,我认为故障转移伙伴已经正确解析,但为什么只有一次呢?也许这在我的问题中不太清楚。 - Shagglez
在您的连接字符串中,您将“数据源”设置为“Mirror”,将“故障转移伙伴”设置为“Principal”。因此,每次调用Connection.Open()时,它都会查找您的连接字符串中的“Mirror”并尝试连接,但由于其作为镜像而不是主要部分运行,因此会被拒绝。然后,它将尝试从您的连接字符串中获取故障转移伙伴,“Priciple”被设置为实际上可以工作的原则。 - bennie j
在这种情况下,缓存中没有设置故障转移伙伴,因为它将始终尝试从连接字符串中获取前两个。现在,当发生故障转移时,它将成功连接到您指定的“镜像”并从该服务器读取故障转移。这就是为什么第二次故障转移(或故障恢复)不起作用的原因。 - bennie j

1

如果发生故障转移,您可以清除应用程序池。我知道这不太好;-)

  // ClearAllPools resets (or empties) the connection pool. 
  // If there are connections in use at the time of the call, 
  // they are marked appropriately and will be discarded 
  // (instead of being returned to the pool) when Close is called on them.
  System.Data.SqlClient.SqlConnection.ClearAllPools();

当我们通过SQL Server别名更改底层服务器时,我们使用它来强制执行服务器名称的“刷新”。

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.clearallpools.aspx


我怎样才能知道故障转移已经发生?理论上,如果我的应用程序知道底层数据库的故障转移,我只需更改连接字符串即可。 - Shagglez
你好,如果你想了解发生故障转移的情况,可能需要在你的连接字符串中指定两个服务器,一个是主服务器,另一个是镜像服务器。 - Peter Gfader

0
尝试使用以下connectionString:
connectionString="Data Source=[MSSQLPrincipalServerIP,MSSQLPORT];Failover Partner=[MSSQLMirrorServerIP,MSSQLPORT];Initial Catalog=DatabaseName;Persist Security Info=True;User Id=userName; Password=userPassword.; Connection Timeout=15;"

0

如果您正在使用 .net 开发,可以尝试使用 ObjAdoDBLib 或 PigSQLSrvLib 和 PigSQLSrvCoreLib,这样代码会变得简单。

示例代码:

新建对象
ObjAdoDBLib

Me.ConnSQLSrv = New ConnSQLSrv(Me.DBSrv, Me.MirrDBSrv, Me.CurrDB, Me.DBUser, Me.DBPwd, Me.ProviderSQLSrv)

PigSQLSrvLib 或 PigSQLSrvCoreLib

Me.ConnSQLSrv = New ConnSQLSrv(Me.DBSrv, Me.MirrDBSrv, Me.CurrDB, Me.DBUser, Me.DBPwd)

在镜像数据库故障转移后,执行此方法自动连接到在线数据库。

Me.ConnSQLSrv.OpenOrKeepActive

有关更多信息,请参阅相关链接。

https://www.nuget.org/packages/ObjAdoDBLib/

https://www.nuget.org/packages/PigSQLSrvLib/

https://www.nuget.org/packages/PigSQLSrvCoreLib/


0

解决方案是关闭连接池 Pooling="false"

虽然这对小型应用程序的影响很小,但我还没有测试过每分钟接收数百个请求(或更多)的应用程序,并不确定其影响。有人愿意发表评论吗?


你在原始设置中等待故障转移发生了多久?根据我的最近经验,似乎必须等待指向原始主体的连接池中的所有连接过期,然后才能意识到主服务器已宕机并尝试连接到故障转移伙伴。在我的一些应用程序中,这可能长达15分钟。 - jaminto
说实话我不记得了,但要求是几乎零停机时间,所以无论如何我都不能等那么久。 - Shagglez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接