对,
这两个答案和一个小小的想法让我想到了一个接近答案的东西。
首先澄清一点:
该应用程序是用 C# (2.0+) 编写的,并使用 ADO.NET 与 SQL Server 2005 通信。镜像设置是两台 W2k3 服务器托管主体和镜像,加上第三台服务器托管 express 实例作为监视器。这样做的好处是故障转移对使用数据库的应用程序几乎是透明的,它会为某些连接抛出错误,但基本上一切都会很好地进行。是的,我们得到了奇怪的误报,但重点是让系统以最少的麻烦继续工作,而镜像确实很好地提供了这一点。
此外,问题不在于严重的服务器故障 - 这通常更明显,但由于其他原因(参见上面的误报)进行故障转移,因为我们确实有一些事情由于各种原因无法进行故障转移无论如何,我们可以看看我们是否可以确定我们得到误报的情况。
因此,鉴于上述情况,仅检查框的状态是不够的,并且通过事件日志追踪可能过于复杂 - 事实证明,答案相当简单:sp_helpserver
sp_helpserver 返回的第一列是服务器名称。如果您定期运行请求,保存以前的服务器名称并每次进行比较,您将能够识别何时发生更改,然后采取适当的措施。
以下是演示主体的控制台应用程序 - 虽然它需要一些工作(例如,连接应该是非池化的并且每次都是新的)但现在已经足够了(所以我会接受这个作为“答案” ). 参数是Principal, Mirror, Database
using System;
using System.Data.SqlClient;
namespace FailoverMonitorConcept
{
class Program
{
static void Main(string[] args)
{
string server = args[0];
string failover = args[1];
string database = args[2];
string connStr = string.Format("Integrated Security=SSPI;Persist Security Info=True;Data Source={0};Failover Partner={1};Packet Size=4096;Initial Catalog={2}", server, failover, database);
string sql = "EXEC sp_helpserver";
SqlConnection dc = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand(sql, dc);
Console.WriteLine("Connection string: " + connStr);
Console.WriteLine("Press any key to test, press q to quit");
string priorServerName = "";
char key = ' ';
while(key.ToString().ToLower() != "q")
{
dc.Open();
try
{
string serverName = cmd.ExecuteScalar() as string;
Console.WriteLine(DateTime.Now.ToLongTimeString() + " - Server name: " + serverName);
if (priorServerName == "")
{
priorServerName = serverName;
}
else if (priorServerName != serverName)
{
Console.WriteLine("***** SERVER CHANGED *****");
Console.WriteLine("New server: " + serverName);
priorServerName = serverName;
}
}
catch (System.Data.SqlClient.SqlException ex)
{
Console.WriteLine("Error: " + ex.ToString());
}
finally
{
dc.Close();
}
key = Console.ReadKey(true).KeyChar;
}
Console.WriteLine("Finis!");
}
}
}
如果没有 a) 提出问题,然后 b) 得到让我真正思考的回答,我就不会到达这里
墨菲