Sql Server 2005 Connection Limit - sql-server

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.

Related

How to perform XA transactions using SQLServer client ODBC driver in C/C++ on Linux?

I've managed to perform XA transactions using SQLServer OLEDB driver on Windows. Now I've ported the C++ application to Linux. On Linux Microsoft provides the SQLServer 2019 ODBC driver and since version 17.3 of this driver, XA is reported to be supported.
Microsoft provides following example that illustrates how to implement the xa_* functions:
Using XA Transactions
The example itself works. Using the code in another context doesn't work. The call to SQLSetConnectAttr(..., SQL_ATTR_ENLIST_IN_XA, ...) for operation OP_START fails and I don't get useful information by CheckRC().
How to get more informaton about failing SQL_ATTR_ENLIST_IN_XA?
How does XA work with the SQL_ATTR_ENLIST_IN_XA approach compared to OLEDB?
Is it possible to change the isolation level in XA mode?
Share your experiences and details with us, please.
Strict XID data layout
The SQLSetConnectAttr(..., SQL_ATTR_ENLIST_IN_XA, ...) function is very sensitive regarding the XID. If the XID has a branch ID then the branch ID must start at byte 64 of xid_t::data. Storing a global ID like "f9707929-a367-4e3a-9a80-3fbb3a23ab11" + branch ID "1234" directly in one sequence and identifiying the string layout by xid_t::gtrid_length and xid_t::bqual_length will work with other DB APIs and IBM MQ, but it fails with SQL_ATTR_ENLIST_IN_XA in SQLServer.
In order to get above sample XID work the UUID has to be stored at the beginning of xid_t::data (byte 0-36) and the branch id has to be stored staring at byte (64-68). The xid_t field gtrid_length has to be set to 36 and bqual_length to 4. The formatID I set to 1.
If the XID layout doesn't fit the SQL_ATTR_ENLIST_IN_XA with operation OP_START fails and SQLGetDiagRec() reports nothing about it.
Setting the isolation level
By default a XA transaction runs under isolation level "Serializable". Microsoft describes this isolation leve as follows:
The highest level where transactions are completely isolated from one another. The SQLServer keeps read and write locks acquired on selected data to be released at the end of the transaction. Range-locks are acquired when a SELECT operation uses a ranged WHERE clause, especially to avoid phantom reads.
On each call to xa_start the isolation level is set to "Serializable". Setting the isolation level using SQLSetConnectAttr(..., SQL_ATTR_TXN_ISOLATION, ...) after connect doesn't help. You have to call this after SQLSetConnectAttr(..., SQL_ATTR_ENLIST_IN_XA, OP_START, ...).
Doing so allows you to set the isolation level for instance to SQL_TXN_READ_COMMITTED. The database option READ_COMMITTED_SNAPSHOT will be also be considered. This means setting isolation level to SQL_TXN_READ_COMMITTED and having database option READ_COMMITTED_SNAPSHOT enabled will switch the isolation level to "Snapshot".
The command "DBCC useroptions" can be used to query the isolation level of the current session.
Following query is also useful for checking the isolation level and status of active transactions:
SELECT tst.session_id, [database_name] = db_name(s.database_id)
, tat.transaction_begin_time
, transaction_duration_s = datediff(s, tat.transaction_begin_time, sysdatetime())
, transaction_type = CASE tat.transaction_type WHEN 1 THEN 'Read/write transaction'
WHEN 2 THEN 'Read-only transaction'
WHEN 3 THEN 'System transaction'
WHEN 4 THEN 'Distributed transaction' END
, input_buffer = ib.event_info, tat.transaction_uow
, transaction_state = CASE tat.transaction_state
WHEN 0 THEN 'The transaction has not been completely initialized yet.'
WHEN 1 THEN 'The transaction has been initialized but has not started.'
WHEN 2 THEN 'The transaction is active - has not been committed or rolled back.'
WHEN 3 THEN 'The transaction has ended. This is used for read-only transactions.'
WHEN 4 THEN 'The commit process has been initiated on the distributed transaction.'
WHEN 5 THEN 'The transaction is in a prepared state and waiting resolution.'
WHEN 6 THEN 'The transaction has been committed.'
WHEN 7 THEN 'The transaction is being rolled back.'
WHEN 8 THEN 'The transaction has been rolled back.' END
, trn_iso_level = CASE s.transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'ReadUncommitted'
WHEN 2 THEN 'ReadCommitted'
WHEN 3 THEN 'RepeatableRead'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot' END
, transaction_name = tat.name, request_status = r.status
, tst.is_user_transaction, tst.is_local
, session_open_transaction_count = tst.open_transaction_count
, s.host_name, s.program_name, s.client_interface_name, s.login_name, s.is_user_process
FROM sys.dm_tran_active_transactions tat
INNER JOIN sys.dm_tran_session_transactions tst on tat.transaction_id = tst.transaction_id
INNER JOIN Sys.dm_exec_sessions s on s.session_id = tst.session_id
LEFT OUTER JOIN sys.dm_exec_requests r on r.session_id = s.session_id
CROSS APPLY sys.dm_exec_input_buffer(s.session_id, null) AS ib;
The Advantage of SQLServer ODBC driver SQL_ATTR_ENLIST_IN_XA
Implementing SQLServer XA with the OLEDB driver and ITransactionJoin interface directly communicates with the local distributed transaction controller (DTC) service. In case the SQLServer is running on another host then the local DTC and the DTC on the SQLServer host are involved. The DTC service must communicate over network. RPC, dynamic port ranges, firewall and security settings often makes this very difficult getting it to work.
With the new ODBC SQL_ATTR_ENLIST_IN_XA interace the DTC to DTC communication is no longer needed. The appliction has only a connection to the SQLServer database instance and on the SQLServer host the DTC service must run and the "XA option" must be set in this DTC. The application that utilizes SQL_ATTR_ENLIST_IN_XA doesn't require a local DTC.

SQL Server Distributed queries with Teradata

I am trying to get distributed queries to run on SQL Server 2012 with a linked server to Teradata.
Connection works fine and query returns quickly if I pass the where clause into the remote SQL using openquery e.g.
select *
from openquery(td, 'select * from lib.purchases where z_PO = ''123456''')
However the below does not run as expected: SQL Server loads the entire table and performs a local filter:
select *
from openquery(td, 'select * from lib.purchases') where z_PO = '123456'
The source table has 100M records.
Obviously index play no role here as query runs just fine on TD side.
What I have tried:
sp_configure 'Ad Hoc Distributed Queries', 1
set Collation Compatible" = True on the linked server properties
Instead of 2, set Collation Name = Latin1_BIN to match (closely?) TD character set (ASCII).
Not sure collation is the issue as I get same result when filtering on numeric fields.
Somehow the so-called query optimizer in SQL Server does not push simple filtering down to the remote server.
Is this the ODBC driver's fault (using 16.10) - a setting, a bug? SQL Server 2012 (v11.0.6248.0) setting I am missing (or path req'd)?
Below is the OLEDB for ODBC properties that I capture in SQL Profiler:
<ProviderInformation>
<Provider>MSDASQL</Provider>
<LinkedServer>td</LinkedServer>
<ProviderCapabilitiesAndSettings>
<Ansi92EntrySupport>0</Ansi92EntrySupport>
<ODBCCoreSupport>1</ODBCCoreSupport>
<ODBCMinimumSupport>1</ODBCMinimumSupport>
<SimpleGrammarSupport>0</SimpleGrammarSupport>
<AnsiLikeSupport>0</AnsiLikeSupport>
<SQLLikeSupport>1</SQLLikeSupport>
<DateLiteralsSupport>0</DateLiteralsSupport>
<GroupBySupport>0</GroupBySupport>
<InnerJoinSupport>0</InnerJoinSupport>
<SubqueriesSupport>0</SubqueriesSupport>
<SimpleUpdatesSupport>0</SimpleUpdatesSupport>
<HistogramsSupport>0</HistogramsSupport>
<ColumnLevelCollationSupport>0</ColumnLevelCollationSupport>
<ConnectionSharingSupport>0</ConnectionSharingSupport>
<MultipleActiveRowsetsSupport>0</MultipleActiveRowsetsSupport>
<MultipleResultsSupport>1</MultipleResultsSupport>
<AllowLimitingRowsReturned>1</AllowLimitingRowsReturned>
<NullConcatenationYieldsNull>0</NullConcatenationYieldsNull>
<StructuredStorageAccessToLargeObjects>1</StructuredStorageAccessToLargeObjects>
<MultipleConcurrentLargeObjectSupport>0</MultipleConcurrentLargeObjectSupport>
<DynamicParametersSupport>1</DynamicParametersSupport>
<NestedQueriesSupport>1</NestedQueriesSupport>
<IndicesAvailableAsAccessPath>0</IndicesAvailableAsAccessPath>
<AllowDataAccessByReference>1</AllowDataAccessByReference>
<RowsetChangesAreVisible>0</RowsetChangesAreVisible>
<RowsetSupportsAppendOnly>0</RowsetSupportsAppendOnly>
<UseLevelZeroOledbInterfacesOnly>0</UseLevelZeroOledbInterfacesOnly>
<RowsetUpdatability>1</RowsetUpdatability>
<AsynchronousRowsetProcessingSupport>0</AsynchronousRowsetProcessingSupport>
<DataSourceUnicodeLocaleId>0</DataSourceUnicodeLocaleId>
<DataSourceUnicodeComparisonStyle>0</DataSourceUnicodeComparisonStyle>
<DataSourceCollationComparisonFlags>0</DataSourceCollationComparisonFlags>
<DataSourceCharacterset></DataSourceCharacterset>
<DataSourceSortOrder></DataSourceSortOrder>
<DataSourceNullCollationOrder>4</DataSourceNullCollationOrder>
<CurrentDbCollationSameAsDefaultRemoteDbCollation>0</CurrentDbCollationSameAsDefaultRemoteDbCollation>
<UnicodeLiteralSupport>0</UnicodeLiteralSupport>
<UnicodeLiteralPrefix></UnicodeLiteralPrefix>
<UnicodeLiteralSuffix></UnicodeLiteralSuffix>
<DateLiteralPrefix></DateLiteralPrefix>
<DateLiteralSuffix></DateLiteralSuffix>
<ObjectNameConstructionFlags>54</ObjectNameConstructionFlags>
<SchemaSeparator>.</SchemaSeparator>
<CatalogSeparator>.</CatalogSeparator>
<QuoteSeparator>"</QuoteSeparator>
<BitRemoting>0</BitRemoting>
<UnicodeLiterals>0</UnicodeLiterals>
<ProviderOledbVersion>131072</ProviderOledbVersion>
<HalloweenProtectionNeeded>1</HalloweenProtectionNeeded>
<RowsetUsableAcrossThreads>0</RowsetUsableAcrossThreads>
<ObjectNameIsSinglePart>0</ObjectNameIsSinglePart>
<Cardinality>-1</Cardinality>
<BookmarkSupport>0</BookmarkSupport>
<BookmarksReusable>0</BookmarksReusable>
<TableFlags>0</TableFlags>
</ProviderCapabilitiesAndSettings>
and here the details of the column in the filter:
DBCOLUMNINFO>
<pwszName>z_PO</pwszName>
<pTypeInfo>0x0000000000000000</pTypeInfo>
<iOrdinal>53</iOrdinal>
<dwFlags>120</dwFlags>
<ulColumnSize>10</ulColumnSize>
<wType>129</wType>
<bPrecision>255</bPrecision>
<bScale>255</bScale>
<DBID>
<eKind>DBKIND_NAME</eKind>
<uName.pwszName>z_PO</uName.pwszName>
</DBID>
</DBCOLUMNINFO>
As a FYI, the context is wrapping the openquery, joined with local data, into a SQL Server view, which is the only thing users would see - from there, they can apply any filter (WHERE) within PowerQuery (XL) or PowerBI. A way to circumvent the lack of DirectQuery support through ODBC.

Amazon RDS SQL Server: how to detect if it is RDS?

I am trying to port my database to RDS. Need to do some changes because of restrictions.
Is it possible to detect inside script (stored procedure etc) that current database is in RDS?
Upd.
I use for the testing this way in my function:
if CHARINDEX(N'EC2AMAZ',(cast(serverproperty('ServerName') as nvarchar(256))))>0
return 1
else
return 0
I liked #xiani's approach, and decided to enhance it slightly (in the event a "normal" instance of SQL Server has an [rdsadmin] database).
DECLARE #IsAmazonRDS BIT = 0;
--1st test: does the [rdsadmin] database exist?
IF DB_ID('rdsadmin') IS NOT NULL
BEGIN
BEGIN TRY
--2nd test: If this is an Amazon RDS instance, we should not able to access the database "model" under the current security context.
DECLARE #FileCount INT;
SELECT #FileCount = COUNT(*) FROM model.sys.database_files;
END TRY
BEGIN CATCH
SET #IsAmazonRDS = 1;
--Comment/uncomment to verify the flag is set.
--SELECT 'Inside Catch';
END CATCH
END
This could be supplemented with 3rd, 4th, etc. additional checks based on whatever criteria you determine. Decide for yourself how far you want to take it.
It's not foolproof, and depends on the rdsadmin database (that AWS always seems to create) existing, but I use this:
SELECT CASE WHEN db_id('rdsadmin') IS NULL THEN 0 ELSE 1 END AS RDS_DATABASE;
I use this way in my function:
if CHARINDEX(N'EC2AMAZ',(cast(serverproperty('ServerName') as nvarchar(256))))>0
return 1
else
return 0
For now it works.

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

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.

Performance issues on ASP.NET MVC 2 with SQL Server

EDIT: I think it's a problem on the subquery on the LINQ-generated query, it get all the records... But I don't know how could I fix it
I have made a simple ASP.NET MVC 2 application that does SELECT queries on a view, I get really poor performance, and while doing a simple benchmark with jMeter (10 conccurents connection) while disabling the cache (I don't want everything to rely on the non customizable/extreme OutputCache)
I see that the SQL Server get overloaded, consuming a LOT of CPU (up to 100%) and all its reserved memory space (512MB)
Here is the action code that cause the problems (manual transactions because it cause DeadLock with the other program that insert new data on the database) :
public ActionResult Index(int page = 0)
{
IronViperEntities db = new IronViperEntities();
db.Connection.Open();
DbTransaction transaction = db.Connection.BeginTransaction(IsolationLevel.ReadUncommitted);
var messages = (from globalView in db.GlobalViews orderby globalView.MessagePostDate descending select globalView).Skip(page*perPage).Take(perPage);
transaction.Commit();
db.Connection.Close();
ViewData["page"] = page;
ViewData["messages"] = messages;
return View();
}
Here is the query executed on the database :
SELECT TOP (100)
[Extent1].[MessageId] AS [MessageId],
[Extent1].[MessageUuid] AS [MessageUuid],
[Extent1].[MessageData] AS [MessageData],
[Extent1].[MessagePostDate] AS [MessagePostDate],
[Extent1].[ChannelName] AS [ChannelName],
[Extent1].[UserName] AS [UserName],
[Extent1].[UserUuid] AS [UserUuid],
[Extent1].[ChannelUuid] AS [ChannelUuid]
FROM ( SELECT [Extent1].[MessageId] AS [MessageId], [Extent1].[MessageUuid] AS [MessageUuid], [Extent1].[MessageData] AS [MessageData], [Extent1].[MessagePostDate] AS [MessagePostDate], [Extent1].[ChannelName] AS [ChannelName], [Extent1].[UserName] AS [UserName], [Extent1].[UserUuid] AS [UserUuid], [Extent1].[ChannelUuid] AS [ChannelUuid], row_number() OVER (ORDER BY [Extent1].[MessagePostDate] DESC) AS [row_number]
FROM (SELECT
[GlobalView].[MessageId] AS [MessageId],
[GlobalView].[MessageUuid] AS [MessageUuid],
[GlobalView].[MessageData] AS [MessageData],
[GlobalView].[MessagePostDate] AS [MessagePostDate],
[GlobalView].[ChannelName] AS [ChannelName],
[GlobalView].[UserName] AS [UserName],
[GlobalView].[UserUuid] AS [UserUuid],
[GlobalView].[ChannelUuid] AS [ChannelUuid]
FROM [dbo].[GlobalView] AS [GlobalView]) AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 0
ORDER BY [Extent1].[MessagePostDate] DESC
View Code :
SELECT dbo.Messages.Id AS MessageId, dbo.Messages.Uuid AS MessageUuid, dbo.Messages.Data AS MessageData, dbo.Messages.PostDate AS MessagePostDate,
dbo.Channels.Name AS ChannelName, dbo.Users.Name AS UserName, dbo.Users.Uuid AS UserUuid, dbo.Channels.Uuid AS ChannelUuid
FROM dbo.Messages INNER JOIN
dbo.Users ON dbo.Messages.UserId = dbo.Users.Id INNER JOIN
dbo.Channels ON dbo.Messages.ChannelId = dbo.Channels.Id
I don't think the server hardware is a problem, I can run equivalent Rails/Grails application without any performance issue. (Dual Core, 3Gb of RAM)
A select count(*) on GlobalView returns ~270.000 lines, indexes are daily rebuilt and a explain show it uses all the clustered indexes.
I get an HTTP average response time of 8000ms, the SQL Server Management Studio shows an average CPU time for this SQL query of 866ms and an average logical IO of 7,592.03.
Database file size if ~180MB
I am using Windows Server 2008 R2 Enterprise Edition, ASP.NET MVC 2 with IIS 7.5 and SQL Server 2008 R2 Express Edition with Advanced Services. They are the only things running on this server.
What can I do ?
Thank you
I guess you got the query from SQL Server Profiler. Save the result, and pass it into the Database Engine Tuning Advisor. That might help you create additional indexes and statistics.
Just out of curiosity: wouldn't appending a .ToList() to the end of the var messages = ... line help?
I've found the probleme,
I replaced "orderby globalView.MessagePostDate descending" by "orderby globalView.MessageId descending", because there isn't any index on MessagePostDate, and that is muuuuch better !
Thank you

Resources