简体   繁体   中英

SQL Queue stops working and fills up with messages

currently I'm struggling with the SQL broker. Everything seems to be configured well, but the queue stops working and fills up with unsent messages. The broker and the queue are enabled. If i drop the queue and the service and recreate them, it works for a while but stops again later. I don't see any important error in the sql server log. So what could cause the error?

Thanks

QUEUE

CREATE QUEUE [dbo].[DataChangeQueue] WITH STATUS = ON , RETENTION = OFF , ACTIVATION (  STATUS = ON , PROCEDURE_NAME = [dbo].[DataChangeQueueProc] , MAX_QUEUE_READERS = 100 , EXECUTE AS N'dbo'), POISON_MESSAGE_HANDLING (STATUS = ON)  ON [PRIMARY]

SERVICE

CREATE SERVICE [DataChangeService]  AUTHORIZATION [dbo]  ON QUEUE [dbo].[DataChangeQueue] ([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])

C#

    public DatabaseNotificationService()
    {
        SqlDependency.Start(m_SQLConnectionString, "DataChangeQueue");

        if (IsAccessGranted())
        {
            ConnectToDatabase();
        }
    }

    ~DatabaseNotificationService()
    {
        SqlDependency.Stop(m_SQLConnectionString, "DataChangeQueue");
    }


    private void ConnectToDatabase()
    {
        using (SqlConnection sqlConnection = new SqlConnection(m_SQLConnectionString))
        {
            sqlConnection.Open();

            using (SqlCommand sqlCommand = sqlConnection.CreateCommand())
            {
                sqlCommand.CommandType = CommandType.Text;
                sqlCommand.CommandText = GetSQLCommandText();
                sqlCommand.Notification = null;

                if (m_SQLDependency != null)
                {
                    m_SQLDependency.OnChange -= DependencyOnChange;
                    m_SQLDependency = null;
                }

                m_SQLDependency = new SqlDependency(sqlCommand, "Service=DataChangeService;Local Database=aspnetdb", 1800);
                m_SQLDependency.OnChange += DependencyOnChange;

                sqlCommand.ExecuteReader();
            }

            sqlConnection.Close();
        }
    }


    private void DependencyOnChange(object sender, SqlNotificationEventArgs e)
    {
        using (SqlConnection sqlConnection = new SqlConnection(m_SQLConnectionString))
        {
            sqlConnection.Open();

            using (SqlCommand cmd2 = sqlConnection.CreateCommand())
            {
                cmd2.CommandType = CommandType.Text;
                cmd2.CommandText = GetOnChangeSQLCommandText();

                using (SqlDataReader sqlDataReader = cmd2.ExecuteReader())
                {
                    if (sqlDataReader != null)
                    {
                        sqlDataReader.Read();

                        List<String> keys = new List<String>(m_Clients.Keys);
                        foreach (String key in keys)
                        {
                            IDatabaseNotificationCallbackContract client;
                            if (m_Clients.TryGetValue(key, out client))
                            {
                                if (((ICommunicationObject)client).State == CommunicationState.Opened)
                                {
                                    client.SendNotificationToClients(sqlDataReader.GetValue(0).ToString());
                                }
                                else
                                {
                                    m_Clients.Remove(key);
                                }
                            }                    
                        }
                    }
                }
            }

            sqlConnection.Close();
        }

        if (m_SQLDependency != null)
        {
            m_SQLDependency.OnChange -= DependencyOnChange;
            m_SQLDependency = null;
        }

        //Reconnect to database for listening to following changes.
        ConnectToDatabase();
    }

When the queue "stops" is it still enabled?

If not, you might be dealing with a poison message in your queue. They can stop processing

I recommend inspecting the first message and see if it is valid for your processing.

If it is not, then pop it off.

Here is the code I would use to delete the first conversation (and therefore poison message) off of a message queue:

BEGIN TRANSACTION;

DECLARE @handle nvarchar(100);
RECEIVE TOP(1) @handle = [conversation_handle] FROM yourQueueName;

END CONVERSATION (@handle)
    WITH ERROR = 127 DESCRIPTION = N'Unable to process message.' ;
GO

COMMIT TRANSACTION;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM