镜像的SQL Server数据库故障转移后如何获得通知

时间:2020-03-05 18:43:22  来源:igfitidea点击:

我们有几个镜像的SQL Server数据库。

我的第一个问题是关键问题是在数据库故障转移时获得通知。我不需要知道,因为erm,它的镜像等等(几乎)全部自动进行,但是建议它会很有用,当我认为我不应该这样做时,我目前正在进行故障转移知道它们何时发生(无需过多挖掘),看看我是否可以确定原因。

我有运行中的服务,可以很容易地使用它来监视此情况,因此替代问题是"如何以编程方式确定哪个是主体,哪个是镜像",这比以尝试依次连接每个方式更聪明(比这通常会工作,但是...)。

谢谢,墨菲

附录:

答案之一询问为什么我不需要知道它何时进行故障转移的答案是我们正在使用ADO.NET开发并且具有自动故障转移支持,我们所要做的就是添加Failover Partner = MIRRORSERVER(其中MIRRORSERVER是连接字符串的镜像服务器实例的名称),代码将透明地进行故障转移,根据哪些连接处于活动状态,我们可能会遇到一些错误,但在我们的情况下很少。

解决方案

回答

如果故障转移逻辑在应用程序中,则可以编写一个状态屏幕,该状态屏幕通过在第一次连接尝试失败时写入var来显示我们连接的是哪个盒子。

我认为最好的选择是ping守护进程/定时任务,该任务会定期检查每个盒子的状态,如果没有响应,则发送电子邮件。

回答

使用Host Monitor http://www.ks-soft.net/hostmon.eng/之类的东西来监视事件日志中与故障转移事件有关的消息,这可以通过电子邮件/ SMS向我们发送警报。

我很好奇,虽然我们不必知道故障转移发生了,因为我们是否不必随后更新应用程序中的数据源以指向故障转移到的新服务器?镜像发生在不同的主机(主主机和镜像)上,而群集中的多个节点从外部看似乎是一个设备。

另外,我们是否正在使用见证服务器以便自动从主服务器故障转移到镜像服务器?这是我所知道的唯一使它自动发生的方法,并且根据我的经验,我们会遇到很多错误的肯定消息,网络打can会欺骗镜子,并以为主数据库实际上已经关闭。

回答

正确的,

这两个答案和一点点思考使我想到了一个接近答案的东西。

首先再澄清一下:

该应用程序是用C(2.0+)编写的,并使用ADO.NET与SQL Server 2005进行通信。
镜像设置是托管主体和镜像的两台W2k3服务器,以及托管快速实例作为监视器的第三台服务器。这样做的好处是,故障转移对于使用数据库的应用程序几乎是透明的,它将对某些连接引发错误,但从根本上讲一切都会很好地进行。是的,我们得到了奇怪的误报,但总的来说是让系统以最少的麻烦进行工作,而镜像确实很好地实现了这一点。

此外,问题还不在于严重的服务器故障(通常更为明显),而是由于其他原因(参见上面的误报)而导致的故障转移,因为由于多种原因,我们确实存在一些无法进行故障转移和故障的事情。无论如何,我们可以看看是否可以识别出误报的情况。

因此,鉴于上述情况,仅检查框的状态还不够,并且追逐事件日志可能过于复杂,事实证明答案很简单: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)得到使我真正想到的答案,我就不会到达这里

墨菲