SQL Server 2008 R2 Express Service Broker 正在使用所有可用内存
我有一个在机器上运行的数据库,用于每秒更新信息。我的所有客户提供的数据都返回到一个源,该源又将数据发布到数据库。这一切都很好,我遇到的问题是我的服务代理和监听更改。
我正在使用 SqlDependency 对象来注册特定查询的侦听器。我按预期收到了事件,但是服务器最终变得不可用。我能够确定 Service Broker 使用了超过 900MB 的内存(使我超过了 Express 的 1GB 限制)。我的印象是我的事件一直留在记忆中而不是清除。每次收到事件时,我都会清除该事件侦听器并注册一个新事件侦听器。有没有更合适的方法来从数据库中清除该事件?
另外,我读过所有内容,每次注册新事件时都必须调用 Stop 和 Start。根据我的经验,第二次调用 stop 总是永远挂起。另外,如果 stop 清除所有事件,我有多个侦听器,当我收到一个侦听器时,我不想停止其他侦听器。
这是我用来注册和响应事件的代码:
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.DatabseEventConnectionString))
{
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT Field1, Field2, Field3, Field4 FROM dbo.Table";
cmd.Notification = null;
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler(dependency_OnChange);
cn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle read here;
}
}
}
void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
// If InvokeRequired returns True, the code
// is executing on a worker thread.
if (Dispatcher.CheckAccess())
{
SqlDependency dep = sender as SqlDependency;
dep.OnChange -= new OnChangeEventHandler(dependency_OnChange);
RegisterTableListener();
}
else
{
// Create a delegate to perform the thread switch.
OnChangeEventHandler tempDelegate =
new OnChangeEventHandler(dependency_OnChange);
object[] args = { sender, e };
// Marshal the data from the worker thread
// to the UI thread.
Dispatcher.Invoke(tempDelegate, args);
}
}
知道为什么内存永远在攀升吗?
I have a database running on a machine that serves the purpose of updating information on a second by second basis. All of my clients provided data all come back to one source, which in turn publishes the data to the database. All this is fine, the problem I am having is with my service broker and listening to changes.
I am using the SqlDependency object to register listeners for specific queries. I get the events as expected, however the server eventually becomes unusable. I was able to determine the Service Broker is using over 900MB of memory (pushing me over the 1GB limit for express). I have the impression that my events are staying in memory and not clearing out. Every time I get an event, I clear out that event listener and register a new one. Is there a more proper way to clean up that event from the database?
Also, I have read all over that you have to call Stop and Start every time you register a new event. In my experience, calling stop a second time always hangs forever. Also, if stop clears all events, I have multiple listeners and I wouldnt want to halt the other ones when I receive one.
Here is the code I am using to register and respond to events:
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.DatabseEventConnectionString))
{
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT Field1, Field2, Field3, Field4 FROM dbo.Table";
cmd.Notification = null;
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler(dependency_OnChange);
cn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
// Handle read here;
}
}
}
void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
// If InvokeRequired returns True, the code
// is executing on a worker thread.
if (Dispatcher.CheckAccess())
{
SqlDependency dep = sender as SqlDependency;
dep.OnChange -= new OnChangeEventHandler(dependency_OnChange);
RegisterTableListener();
}
else
{
// Create a delegate to perform the thread switch.
OnChangeEventHandler tempDelegate =
new OnChangeEventHandler(dependency_OnChange);
object[] args = { sender, e };
// Marshal the data from the worker thread
// to the UI thread.
Dispatcher.Invoke(tempDelegate, args);
}
}
Any idea as to why the memory is forever climbing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Microsoft SqlDependency 类有特定的行为。即使您调用 SqlDependency.Stop() 方法,释放 SqlCommand 和 SqlConnection - 它仍然在数据库中保留会话组 (sys.conversation_groups) 和会话端点 (sys.conversation_endpoints)。看起来 SQL Server 加载每个会话端点并使用所有允许的内存。 这里测试证明了这一点。因此,要清理所有未使用的对话端点并释放所有占用的内存,您必须为数据库启动此 SQL 代码:
此外,SqlDependency 并不给您机会接收表的所有更改。因此,您在 SqlDependency 重新订阅期间不会收到有关更改的通知。
为了避免所有这些问题,我使用了 SqlDependency 类的另一个开源实现 - SqlDependencyEx。它使用数据库触发器和本机 Service Broker 通知来接收有关表更改的事件。这是一个用法示例:
希望这会有所帮助。
There is specific behavior of Microsoft SqlDependency class. Even though you call SqlDependency.Stop() method, release SqlCommand and SqlConnection - it still keep conversation groups (sys.conversation_groups) and conversation endpoints (sys.conversation_endpoints) in the database. It looks like SQL Server loads every conversation endpoint and uses all allowed memory. Here tests that prove it. So, to clean all unused conversation endpoints and release all occupied memory you have to start this SQL code for your database:
Also, SqlDependency doesn't give you an opportunity to receive ALL changes of the table. So, you don't receive notification about changes during SqlDependency resubscription.
To avoid all these problems I'd used another open source realization of SqlDependency class - SqlDependencyEx. It uses database trigger and native Service Broker notification to receive events about changes of the table. This is an usage example:
Hope this helps.
我不是专家,但是......
你尝试过:
并可能改变
dep.OnChange -= new OnChangeEventHandler(dependency_OnChange);
到
dep.OnChange -= dependency_OnChange;
I am not an expert, but...
Have you tried:
and possibly changing
dep.OnChange -= new OnChangeEventHandler(dependency_OnChange);
to
dep.OnChange -= dependency_OnChange;