The Problem:
Applications utilizing the SqlDependency
class for SQL Server database change monitoring can experience memory leaks. Expired SqlDependency
objects accumulate in memory, potentially exhausting system resources.
Root Cause:
SqlDependency
establishes a server connection and registers table notifications. Even after dependency removal or resource release (SqlCommand
, SqlConnection
), associated conversation groups and endpoints persist in the database, consuming memory.
Solution: Database Cleanup
To reclaim memory occupied by expired SqlDependency
objects, execute this SQL script within the affected database:
<code class="language-sql">DECLARE @ConvHandle uniqueidentifier DECLARE Conv CURSOR FOR SELECT CEP.conversation_handle FROM sys.conversation_endpoints CEP WHERE CEP.state = 'DI' or CEP.state = 'CD' OPEN Conv; FETCH NEXT FROM Conv INTO @ConvHandle; WHILE (@@FETCH_STATUS = 0) BEGIN END CONVERSATION @ConvHandle WITH CLEANUP; FETCH NEXT FROM Conv INTO @ConvHandle; END CLOSE Conv; DEALLOCATE Conv;</code>
SqlDependency Limitations:
Beyond memory management, SqlDependency
has inherent limitations:
Alternative: SqlDependencyEx Library
For improved reliability and comprehensive change tracking, consider the open-source SqlDependencyEx
library. It uses database triggers and Service Broker for more robust notification:
<code class="language-csharp">int changesReceived = 0; using (SqlDependencyEx sqlDependency = new SqlDependencyEx( TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) { sqlDependency.TableChanged += (o, e) => changesReceived++; sqlDependency.Start(); // Simulate table changes. MakeTableInsertDeleteChanges(changesCount); // Allow time for change notification. Thread.Sleep(1000); } Assert.AreEqual(changesCount, changesReceived);</code>
The above is the detailed content of How to Resolve SQL Server Memory Leaks Caused by Expired SqlDependency Objects?. For more information, please follow other related articles on the PHP Chinese website!