Service Broker messages start to get hung up after about a day - sql-server

I have an application that is using the Service Broker is SQL 2008. About once a day the database's performance starts take a noticeable hit and I have determined that this is because of the Service Broker. If I hard reset all broker connections using the following commands:
ALTER DATABASE [RegencyEnterprise] SET OFFLINE WITH ROLLBACK IMMEDIATE
ALTER DATABASE [RegencyEnterprise] SET ONLINE
Then the performance returns to normal until about the next day. I have also noticed that when performance is poor, running the following query returns a large number (around 1000 currently) of conversations that are stuck in the STARTED_OUTBOUND state:
SELECT * FROM sys.conversation_endpoints
Also, the following queries don't return any entries in them:
SELECT * FROM sys.dm_qn_subscriptions
SELECT * FROM sys.transmission_queue
Performance seems to be alright where there are plenty of items returned by this query. The only time when there are problems are when there are connections that are STARTED_OUTBOUND that stay stuck in this state.
The only configuration I have done to the Service Broker on my SQL Server 2008 instance was to run the following command:
ALTER DATABASE RegencyEnterprise SET ENABLE_BROKER
Digging through the SQL error log, I have found this entry over 1000 times as well:
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 &apos;SqlQueryNotificationService-cb4e7a77-58f3-4f93-95c1-261954d3385a&apos; because it does not exist.</Description></Error>'.
I also see this error a dozen or so times throughout the log, though I believe I can fix this just by creating a master key in the database:
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.
I am thinking the number of these errors may be related to the number of conversations that are staying stuck in the queue. Here is the C# code I am using to subscribe to the query notifications:
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();
}
}
Here is how I handle the notification:
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...>
}
Does anyone know what can cause the broker's connections to get in this state? Or what tools I could use to go about trying to figure out what is causing this? I currently only have a single web server that is registering to its notifications, so my scenario is not overly complex.
UPDATE:
Ok, so I have determined from this post that the error "Cannot find the remote service ... because it does not exist" is due to SqlDependency not cleaning up after itself properly. The broker is still trying to send notifications to my application after the service has ended. So now, it sounds like I just have to find a way to clear out whatever it is not properly cleaning up when my app starts before calling SqlDependency.Start(), but I have not found a way to do this other than my original method above, which takes the database offline and is not acceptable. Does anyone know know to clean this up?

I have found an acceptable approach to solving this issue. First, I migrated my code away from SqlDependency and I am now using SqlNotificationRequest instead. Doing this prevents Broker Queues and Services from being created/destroyed at unexpected times.
Even with this however, when my application exits there are still a few conversations that don't get marked as closed because the original endpoint that setup the notification is no longer there. Therefore, each time my server re-initializes my code I am clearing out existing conversations.
This adjustment has reduced the number of connections that I have on a daily bases from over 1000 and having to manually kill them, to having a max of about 20 at all times. I highly recommend using SqlNotificationRequest instead of SqlDependency.

I have found a way to clear out the conversations that are stuck. I retrieve all of the generated SqlDependency queues that still exist and iterate over the conversations that don't belong to any of these and end those conversations. Below is the code:
SET NOCOUNT OFF;
DECLARE #handle UniqueIdentifier
DECLARE #count INT = 0
-- Retrieve orphaned conversation handles that belong to auto-generated SqlDependency queues and iterate over each of them
DECLARE handleCursor CURSOR
FOR
SELECT [conversation_handle]
FROM sys.conversation_endpoints WITH(NOLOCK)
WHERE
far_service COLLATE SQL_Latin1_General_CP1_CI_AS like 'SqlQueryNotificationService-%' COLLATE SQL_Latin1_General_CP1_CI_AS AND
far_service COLLATE SQL_Latin1_General_CP1_CI_AS NOT IN (SELECT name COLLATE SQL_Latin1_General_CP1_CI_AS FROM sys.service_queues)
DECLARE #Rows INT
SELECT #Rows = COUNT(*) FROM sys.conversation_endpoints WITH(NOLOCK)
WHERE
far_service COLLATE SQL_Latin1_General_CP1_CI_AS like 'SqlQueryNotificationService-%' COLLATE SQL_Latin1_General_CP1_CI_AS AND
far_service COLLATE SQL_Latin1_General_CP1_CI_AS NOT IN (SELECT name COLLATE SQL_Latin1_General_CP1_CI_AS FROM sys.service_queues)
WHILE #ROWS>0
BEGIN
OPEN handleCursor
FETCH NEXT FROM handleCursor
INTO #handle
BEGIN TRANSACTION
WHILE ##FETCH_STATUS = 0
BEGIN
-- End the conversation and clean up any remaining references to it
END CONVERSATION #handle WITH CLEANUP
-- Move to the next item
FETCH NEXT FROM handleCursor INTO #handle
SET #count= #count+1
END
COMMIT TRANSACTION
print #count
CLOSE handleCursor;
IF #count > 100000
BEGIN
BREAK;
END
SELECT #Rows = COUNT(*) FROM sys.conversation_endpoints WITH(NOLOCK)
WHERE
far_service COLLATE SQL_Latin1_General_CP1_CI_AS like 'SqlQueryNotificationService-%' COLLATE SQL_Latin1_General_CP1_CI_AS AND
far_service COLLATE SQL_Latin1_General_CP1_CI_AS NOT IN (SELECT name COLLATE SQL_Latin1_General_CP1_CI_AS FROM sys.service_queues)
END
DEALLOCATE handleCursor;

Started Outbound means 'SQL Server processed a BEGIN CONVERSATION for this conversation, but no messages have yet been sent.' (from Books Online)
It looks like you are creating conversations that are not then being used, so they never get closed.
Not entirely sure why that would be causing a degradation in performance though.

Related

How do I set the correct transaction level?

I am using Dapper on ADO.NET. So at present I am doing the following:
using (IDbConnection conn = new SqlConnection("MyConnectionString")))
{
conn.Open());
using (IDbTransaction transaction = conn.BeginTransaction())
{
// ...
However, there are various levels of transactions that can be set. I think this is the various settings.
My first question is how do I set the transaction level (where I am using Dapper)?
My second question is what is the correct level for each of the following cases? In each of these cases we have multiple instances of a web worker (Azure) service running that will be hitting the DB at the same time.
I need to run monthly charges on subscriptions. So in a transaction I need to read a record and if it's due for a charge create the invoice record and mark the record as processed. Any other read of that record for the same purpose needs to fail. But any other reads of that record that are just using it to verify that it is active need to succeed.
So what transaction do I use for the access that will be updating the processed column? And what transaction do I use for the other access that just needs to verify that the record is active?
In this case it's fine if a conflict causes the charge to not be run (we'll get it the next day). But it is critical that we not charge someone twice. And it is critical that the read to verify that the record is active succeed immediately while the other operation is in its transaction.
I need to update a record where I am setting just a couple of columns. One use case is I set a new password hash for a user record. It's fine if other access occurs during this except for deleting the record (I think that's the only problem use case). If another web service is also updating that's the user's problem for doing this in 2 places simultaneously.
But it's key that the record stay consistent. And this includes the use case of "set NumUses = NumUses + #ParamNum" so it needs to treat the read, calculation, write of the column value as an atomic action. And if I am setting 3 column values, they all get written together.
1) Assuming that Invoicing process is an SP with multiple statements your best bet is to create another "lock" table to store the fact that invoicing job is already running e.g.
CREATE TABLE InvoicingJob( JobStarted DATETIME, IsRunning BIT NOT NULL )
-- Table will only ever have one record
INSERT INTO InvoicingJob
SELECT NULL, 0
EXEC InvoicingProcess
ALTER PROCEDURE InvoicingProcess
AS
BEGIN
DECLARE #InvoicingJob TABLE( IsRunning BIT )
-- Try to aquire lock
UPDATE InvoicingJob WITH( TABLOCK )
SET JobStarted = GETDATE(), IsRunning = 1
OUTPUT INSERTED.IsRunning INTO #InvoicingJob( IsRunning )
WHERE IsRunning = 0
-- job has been running for more than a day i.e. likely crashed without releasing a lock
-- OR ( IsRunning = 1 AND JobStarted <= DATEADD( DAY, -1, GETDATE())
IF NOT EXISTS( SELECT * FROM #InvoicingJob )
BEGIN
PRINT 'Another Job is already running'
RETURN
END
ELSE
RAISERROR( 'Start Job', 0, 0 ) WITH NOWAIT
-- Do invoicing tasks
WAITFOR DELAY '00:01:00' -- to simulate execution time
-- Release lock
UPDATE InvoicingJob
SET IsRunning = 0
END
2) Read about how transactions work: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/transactions-transact-sql?view=sql-server-2017
https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017
You second question is quite broad.

Emitting application event like objects from SQL Server with Service Broker in nodejs

I want to do something like OracleChangeDatabaseNotitications or PostgreSQL LISTEN/NOTIFY with SQL Server - that is, I want to emit events asynchronously over a connection to the database.
It seems possible to do this from .NET code using ServiceBroker and SQLNotificationServices but I can't find if this is possible to do outside of .NET.
So I tried throwing some JS together.
I used this to setup the ServiceBroker environment.
I can send an event like this:
DECLARE #handle uniqueidentifier
BEGIN DIALOG CONVERSATION #handle
FROM SERVICE MyService
TO SERVICE 'MyRecvService'
ON CONTRACT MyContract;
--Sends a message
SEND ON CONVERSATION #handle
MESSAGE TYPE MyMessage('<message>hello world B</message>')
--And ends the conversation
END CONVERSATION #handle WITH CLEANUP
And I used the mssql package with nodejs to do something like this to try to receive the event:
let queryResult = await request.query(`declare #rh uniqueidentifier;
waitfor(
receive top(1) #rh = conversation_handle
FROM MyRecvQueue
), timeout 20000;
end conversation #rh;
and that DOES return something but only the notification that something happened, not the data.
This is what I get:
query { recordsets: [],
recordset: undefined,
output: {},
rowsAffected: [ 1 ] }
So it looks like a row has been affected but I'm just throwing the conversation away.
Does anyone know if I can get the data back over the connection without doing a further SQL query?
As Jeroen Mostert says... the fix was simple:
let queryResult = await request.query(`declare #rh uniqueidentifier;
waitfor(receive top(1) convert(xml, message_body) [message] FROM MyRecvQueue),
timeout 20000;
end conversation #rh;`);
Does the job.
Thanks!

An unexpected method call was made. Ensure that the XML is well formed. The stack trace of the method call was : Void WriteFullEndElement()

Using BizTalk I am trying to insert/update the table in the SQL Server database using the stored procedure. I have created a stored procedure and the Table Type like below
CREATE TYPE dbo.dept_TT AS TABLE
(
dept_name varchar(64),
jax_dept_id char(32)
)
GO
CREATE PROCEDURE [dbo].[uspInsertorUpdateDept]
#dept_TT dept_TT READONLY
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
UPDATE dep
SET dep.dept_name = dtt.dept_name,
dep.jax_dept_id = dtt.jax_dept_id
FROM [afm].[jax_dept] dep
INNER JOIN #dept_TT dtt ON dep.jax_dept_id = dtt.jax_dept_id
INSERT INTO [afm].[jax_dept](dept_name, jax_dept_id )
SELECT dtt.dept_name, dtt.jax_dept_id
FROM #dept_TT dtt
WHERE NOT EXISTS (SELECT 1
FROM [afm].[jax_dept]
WHERE jax_dept_id = dtt.jax_dept_id)
COMMIT TRANSACTION;
END;
When I execute the stored produre in the SQL Server management studio it insert/updates the records as expected. I am consuming this storedprocedure in the biztalk application and tried to run the application it throws error like
The adapter failed to transmit message going to send port "WcfSendPort_SqlAdapterBinding_Procedures_dbo_Custom_Dep" with URL "mssql://". It will be retransmitted after the retry interval specified for this Send Port. Details:"Microsoft.ServiceModel.Channels.Common.XmlReaderParsingException: An unexpected method call was made. Ensure that the XML is well formed. The stack trace of the method call was : Void WriteFullEndElement().
I enabled the tracking and tried seeing the XML that is sent to the send port and it looks good like below.
<?xml version="1.0" encoding="utf-8"?>
<ns0:uspInsertorUpdateDept xmlns:ns0="http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo" xmlns:ns4="http://schemas.datacontract.org/2004/07/System.Data" xmlns:ns3="http://schemas.microsoft.com/Sql/2008/05/Types/TableTypes/dbo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:dept_TT>
<ns3:dept_TT>
<ns3:dept_name>lab1</ns3:dept_name>
<ns3:jax_dept_id>RRI</ns3:jax_dept_id>
</ns3:dept_TT>
<ns3:dept_TT>
<ns3:dept_name>lab2</ns3:dept_name>
<ns3:jax_dept_id>RAFAC</ns3:jax_dept_id>
</ns3:dept_TT>
</ns0:dept_TT>
</ns0:uspInsertorUpdateDept>
Xml generated for the stored procedure in the VS
<ns0:uspInsertorUpdateDept xmlns:ns0="http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo">
<ns0:dept_TT>
<ns1:dept_TT xmlns:ns1="http://schemas.microsoft.com/Sql/2008/05/Types/TableTypes/dbo">
<ns1:dept_name>dept_namedept_namedept_namedept_namedept_namedept_namedept_named</ns1:dept_name>
<ns1:jax_dept_id>jax_dept_idjax_dept_idjax_dept_i</ns1:jax_dept_id>
</ns1:dept_TT>
<ns1:dept_TT xmlns:ns1="http://schemas.microsoft.com/Sql/2008/05/Types/TableTypes/dbo">\
<ns1:dept_name>dept_namedept_namedept_namedept_namedept_namedept_namedept_named</ns1:dept_name>
<ns1:jax_dept_id>jax_dept_idjax_dept_idjax_dept_i</ns1:jax_dept_id>
</ns1:dept_TT>
<ns1:dept_TT xmlns:ns1="http://schemas.microsoft.com/Sql/2008/05/Types/TableTypes/dbo">
<ns1:dept_name>dept_namedept_namedept_namedept_namedept_namedept_namedept_named</ns1:dept_name>
<ns1:jax_dept_id>jax_dept_idjax_dept_idjax_dept_i</ns1:jax_dept_id>
</ns1:dept_TT>
</ns0:dept_TT>
</ns0:uspInsertorUpdateDept>
Not sure what am I missing here. Any help is greatly appreciated

SQl Server deadlock with simple update statement

Using SQL Server 2008 R2 I am getting deadlocks when the same update statement (with different parameters) is running concurrently. Here is the deadlock graph (sorry cannot post images on here yet):
http://i.stack.imgur.com/E6JBK.png
And here is the actual execution plan:
http://i.stack.imgur.com/emm9i.png
The update is like this:
exec sp_executesql N'UPDATE mapping.IssuerAlternateName
SET
UseCount = UseCount + 1,
MostRecentlyAppeared = GETDATE(),
MostRecentlyAppearedUnderlyingAssetName = #p1
WHERE ID = #p0
',N'#p0 int,#p1 nvarchar(4000)',#p0=1234,#p1=N'blah blah blah'
If I have understood things correctly we are trying to read and write from the same index (PK_IssuerAlternateName_1).
Is there any way to resolve this? I was wondering if adding an additional index to the primary key and using WITH INDEX might fix it by stopping the read of PK_IssuerAlternateName_1 (sorry the full name is truncated in the execution plan screenshot).
Or is the best option just to live with this and retry the transaction, which is how the error is currently handled in .NET client. It is certainly successful on retry, but it would be good to avoid the deadlock if possible.
Thanks
In situations similar to this, I have used the UPDLOCK hint to let the database know I intend to update this row. It is not implied by the UPDATE statement. Without the lock hint, it will first obtain a "shared" lock, and then try to escalate. However, this causes deadlocks in certain scenarios.
You will need to do this within your own TransactionScope to ensure everything works correctly.
var sql = #"UPDATE mapping.IssuerAlternateName with (UPDLOCK)
SET
UseCount = UseCount + 1,
MostRecentlyAppeared = GETDATE(),
MostRecentlyAppearedUnderlyingAssetName = #p1
WHERE ID = #p0";
var options = new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadCommitted // don't use Serializable!
};
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, options))
{
using (var context = new YourDbContext())
{
// execute your command here
}
}

Sql Server 2005 Connection Limit

Is there a connection limit on Sql Server 2005 Developers Edition. We have many threads grabbing connections, and I know ADO.NET does connection pooling, but I get OutOfMemory exceptions. We take out the db connections and it works fine.
This is the response to that question on Euan Garden's (a Program Manager for Visual Studio Team Edition) blog:
There are no limits in terms of memory, db size or procs for DE, it is essentially Enterprise Edition.
There is however a licensing restriction that prevents it from being used in production.
Therefore, you probably just need to make sure you are closing your connection objects properly. The using block will be perfect for such a job...
You may not be closing or disposing of your connection objects correctly. Make sure your code looks something like this:
using (SqlConnection conn = new SqlConnection("connectionstring"))
{
conn.Open();
// database access code goes here
}
The using block will automatically close and dispose of your connection object.
32767 on Enterprise Edition
<ServerProductVersion>9.00.3235.00</ServerProductVersion>
<ServerProductLevel>SP2</ServerProductLevel>
<ServerEdition>Enterprise Edition</ServerEdition>
<ServerEngineEdition>3</ServerEngineEdition>
How I check...
CREATE FUNCTION [dbo].svfV1GetSessionAndServerEnvironmentMetaData
RETURNS xml
AS
BEGIN
-- Declare the return variable here
DECLARE #ResultVar xml
-- Add the T-SQL statements to compute the return value here
SET #ResultVar =
(
SELECT
##SPID as SPID,
##ProcID as ProcId,
##DBTS as DBTS,
getdate() as DateTimeStamp,
System_User as SystemUser,
Current_User as CurrentUser,
Session_User as SessionUser,
User_Name() as UserName,
Permissions() as UserSessionPermissionsBitmap,
Host_Id() as HostId,
Host_Name() as HostName,
App_Name() as AppName,
ServerProperty('ProcessId') as ServerProcessId,
ServerProperty('MachineName') as ServerMachineName,
ServerProperty('ServerName') as ServerServerName,
ServerProperty('ComputerNamePhysicalNetBIOS') as ServerComputerNamePhysicalNetBIOS,
ServerProperty('InstanceName') as ServerInstanceName,
ServerProperty('ProductVersion') as ServerProductVersion,
ServerProperty('ProductLevel') as ServerProductLevel,
##CONNECTIONS as CumulativeSqlConnectionsSinceStartup,
##TOTAL_ERRORS as CumulativeDiskWriteErrorsSinceStartup,
##PACKET_ERRORS as CumulativeNetworkPacketErrorsSinceStartup,
--Note:
--If the time returned in ##CPU_BUSY, or ##IO_BUSY exceeds approximately 49 days of cumulative CPU time,
--you receive an arithmetic overflow warning. In that case,
--the value of ##CPU_BUSY, ##IO_BUSY and ##IDLE variables are not accurate.
-- ##CPU_BUSY * ##TIMETICKS as CumulativeMicroSecondsServerCpuBusyTimeSinceStartup,
-- ##IO_BUSY * ##TIMETICKS as CumulativeMicroSecondsServerIoBusyTimeSinceStartup,
-- ##IDLE * ##TIMETICKS as CumulativeMicroSecondsServerIdleTimeSinceStartup,
ServerProperty('BuildClrVersion') as ServerBuildClrVersion,
ServerProperty('Collation') as ServerCollation,
ServerProperty('CollationID') as ServerCollationId,
ServerProperty('ComparisonStyle') as ServerComparisonStyle,
ServerProperty('Edition') as ServerEdition,
ServerProperty('EditionID') as ServerEditionID,
ServerProperty('EngineEdition') as ServerEngineEdition,
ServerProperty('IsClustered') as ServerIsClustered,
ServerProperty('IsFullTextInstalled') as ServerIsFullTextInstalled,
ServerProperty('IsIntegratedSecurityOnly') as ServerIsIntegratedSecurityOnly,
ServerProperty('IsSingleUser') as ServerIsSingleUser,
ServerProperty('LCID') as ServerLCID,
ServerProperty('LicenseType') as ServerLicenseType,
ServerProperty('NumLicenses') as ServerNumLicenses,
ServerProperty('ResourceLastUpdateDateTime') as ServerResourceLastUpdateDateTime,
ServerProperty('ResourceVersion') as ServerResourceVersion,
ServerProperty('SqlCharSet') as ServerSqlCharSet,
ServerProperty('SqlCharSetName') as ServerSqlCharSetName,
ServerProperty('SqlSortOrder') as ServerSqlSortOrder,
ServerProperty('SqlSortOrderName') as ServerSqlSortOrderName,
##MAX_CONNECTIONS as MaxAllowedConcurrentSqlConnections,
SessionProperty('ANSI_NULLS') as SessionANSI_NULLS,
SessionProperty('ANSI_PADDING') as SessionANSI_PADDING,
SessionProperty('ANSI_WARNINGS') as SessionANSI_WARNINGS,
SessionProperty('ARITHABORT') as SessionARITHABORT,
SessionProperty('CONCAT_NULL_YIELDS_NULL') as SessionCONCAT_NULL_YIELDS_NULL,
SessionProperty('NUMERIC_ROUNDABORT') as SessionNUMERIC_ROUNDABORT,
SessionProperty('QUOTED_IDENTIFIER') as SessionQUOTED_IDENTIFIER
FOR XML PATH('SequenceIdEnvironment')
)
-- Return the result of the function
RETURN #ResultVar
END
on my SQL Server database engine instance returns
<SequenceIdEnvironment>
<SPID>56</SPID>
<ProcId>1666821000</ProcId>
<DBTS>AAAAAAAAB9A=</DBTS>
<DateTimeStamp>2008-10-02T15:09:26.560</DateTimeStamp>
...
<CurrentUser>dbo</CurrentUser>
<SessionUser>dbo</SessionUser>
<UserName>dbo</UserName>
<UserSessionPermissionsBitmap>67044350</UserSessionPermissionsBitmap>
<HostId>3852 </HostId>
...
<AppName>Microsoft SQL Server Management Studio - Query</AppName>
<ServerProcessId>508</ServerProcessId>
...
<ServerProductVersion>9.00.3235.00</ServerProductVersion>
<ServerProductLevel>SP2</ServerProductLevel>
<CumulativeSqlConnectionsSinceStartup>169394</CumulativeSqlConnectionsSinceStartup>
<CumulativeDiskWriteErrorsSinceStartup>0</CumulativeDiskWriteErrorsSinceStartup>
<CumulativeNetworkPacketErrorsSinceStartup>0</CumulativeNetworkPacketErrorsSinceStartup>
<ServerBuildClrVersion>v2.0.50727</ServerBuildClrVersion>
<ServerCollation>SQL_Latin1_General_CP1_CI_AS</ServerCollation>
<ServerCollationId>872468488</ServerCollationId>
<ServerComparisonStyle>196609</ServerComparisonStyle>
<ServerEdition>Enterprise Edition</ServerEdition>
...
<ServerEngineEdition>3</ServerEngineEdition>
<ServerIsClustered>0</ServerIsClustered>
<ServerIsFullTextInstalled>1</ServerIsFullTextInstalled>
<ServerIsIntegratedSecurityOnly>0</ServerIsIntegratedSecurityOnly>
<ServerIsSingleUser>0</ServerIsSingleUser>
...
<ServerResourceLastUpdateDateTime>2008-03-12T18:59:08.633</ServerResourceLastUpdateDateTime>
<ServerResourceVersion>9.00.3235</ServerResourceVersion>
<ServerSqlCharSet>1</ServerSqlCharSet>
<ServerSqlCharSetName>iso_1</ServerSqlCharSetName>
<ServerSqlSortOrder>52</ServerSqlSortOrder>
<ServerSqlSortOrderName>nocase_iso</ServerSqlSortOrderName>
** <MaxAllowedConcurrentSqlConnections>32767</MaxAllowedConcurrentSqlConnections> **
<SessionANSI_NULLS>1</SessionANSI_NULLS>
<SessionANSI_PADDING>1</SessionANSI_PADDING>
<SessionANSI_WARNINGS>1</SessionANSI_WARNINGS>
<SessionARITHABORT>1</SessionARITHABORT>
<SessionCONCAT_NULL_YIELDS_NULL>1</SessionCONCAT_NULL_YIELDS_NULL>
<SessionNUMERIC_ROUNDABORT>0</SessionNUMERIC_ROUNDABORT>
<SessionQUOTED_IDENTIFIER>1</SessionQUOTED_IDENTIFIER>
</SequenceIdEnvironment>
Are the out of memory exceptions from the .NET? If the error was on the server you would probably see a connection refused message instead.

Resources