我有一个使用Service Broker的应用程序是SQL 2008.大约每天一次数据库的性能开始会显着下降,并且我确定这是因为Service Broker。如果我使用以下命令硬复位所有代理连接:服务代理消息在大约一天后开始挂起
ALTER DATABASE [RegencyEnterprise] SET OFFLINE WITH ROLLBACK IMMEDIATE
ALTER DATABASE [RegencyEnterprise] SET ONLINE
然后性能恢复正常,直到第二天。我也注意到,当性能差,运行下面的查询返回被卡在STARTED_OUTBOUND状态谈话的大量(1000目前大约):
SELECT * FROM sys.conversation_endpoints
此外,下面的查询不返回任何其中的条目:
SELECT * FROM sys.dm_qn_subscriptions
SELECT * FROM sys.transmission_queue
性能似乎没问题,其中有大量此查询返回的项目。出现问题的唯一时间是存在STARTED_OUTBOUND的连接停留在此状态的时间。
我已经尽到服务代理我的SQL Server上的唯一配置2008实例是运行以下命令:
ALTER DATABASE RegencyEnterprise SET ENABLE_BROKER
通过SQL错误日志挖掘,我发现这个条目超过1000倍好:
07/11/2013 01:00:02,spid27s,Unknown,The query notification dialog on conversation handle '{6DFE46F5-25E9-E211-8DC8-00221994D6E9}.' closed due to the following error: '<?xml version="1.0"?><Error xmlns="http://schemas.microsoft.com/SQL/ServiceBroker/Error"><Code>-8490</Code><Description>Cannot find the remote service 'SqlQueryNotificationService-cb4e7a77-58f3-4f93-95c1-261954d3385a' because it does not exist.</Description></Error>'.
我也看到这个错误十几次整个日志,但我相信我能解决这个问题只需在数据库中创建一个主键:
06/26/2013 14:25:01,spid116,Unknown,Service Broker needs to access the master key in the database '<Database name>'. Error code:26. The master key has to exist and the service master key encryption is required.
我在想这些错误的数量可能与停留在队列中的对话数量有关。下面是C#代码我使用订阅查询通知:
private void EstablishSqlConnection(
String storedProcedureName,
IEnumerable<SqlParameter> parameters,
Action sqlQueryOperation,
String serviceCallName,
Int32 timeout,
params MultipleResult[] results)
{
SqlConnection storeConnection = (SqlConnection) ((EntityConnection) ObjectContext.Connection).StoreConnection;
try
{
using (SqlCommand command = storeConnection.CreateCommand())
{
command.Connection = storeConnection;
storeConnection.Open();
SqlParameter[] sqlParameters = parameters.ToArray();
command.CommandText = storedProcedureName;
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddRange(sqlParameters);
if (sqlQueryOperation != null)
{
// Register a sql dependency with the SQL query.
SqlDependency sqlDependency = new SqlDependency(command, null, timeout);
sqlDependency.OnChange += OnSqlDependencyNotification;
}
using (DbDataReader reader = command.ExecuteReader())
{
results.ForEach(result => result.MapResults(this, reader));
}
}
}
finally
{
storeConnection.Close();
}
}
这里是我如何处理通知:
public static void OnSqlDependencyNotification(object sender, SqlNotificationEventArgs e)
{
if (e.Info == SqlNotificationInfo.Invalid)
{
// If we failed to register the SqlDependency, log an error
<Error is loged here...>
// If we get here, we are not in a valid state to requeue the sqldependency. However,
// we are on an async thread and should NOT throw an exception. Instead we just return
// here, as we have already logged the error to the database.
return;
}
// If we are able to find and remove the listener, invoke the query operation to re-run the query.
<Handle notification here...>
}
有谁知道是什么导致经纪人的连接,在此得到州?或者我可以使用什么工具来试图找出造成这种情况的原因?我目前只有一台正在注册其通知的Web服务器,所以我的情况并不太复杂。
UPDATE:
好了,我已经从this post确定错误“无法找到远程服务...因为它不存在”是由于的SqlDependency无法正常后自己清理。该代理仍在尝试在服务结束后向我的应用程序发送通知。所以现在,这听起来像我只需要找到一种方法来清除在调用SqlDependency.Start()之前我的应用程序启动时没有正确清理的任何东西,但是我还没有找到一种方法来做到这一点,而不是我的原始方法上面,它使数据库脱机并且不可接受。有谁知道知道清理这件事?
描述您的Service Broker配置。你有什么队列,你如何使用它们,另一端是哪里?等... – RBarryYoung
我只是使用默认值 - 我还没有创建任何自定义队列。我正在使用我的Web应用程序中的C#SqlDependency对象进行连接。是否有具体的配置信息可以帮助? – lehn0058
您能告诉我们C#代码吗? – Rikalous