2

我们有一个应用程序,它通过使用 NHibernate(版本 3.1.0.4000)将记录写入 SQL Server CE(版本 3.5)/(MySQL 5.7.11 社区)数据库表 [取决于配置]。

执行保存到数据库表的方法具有以下结构,因此应正确处理所有内容

using (ISession session = SessionHelper.GetSession())
using (ITransaction txn = session.BeginTransaction())
{
    session.Save(entity);
    txn.Commit();
}

经过大约一周的繁重工作(已写入数十万条记录),应用程序停止工作并引发内存不足错误。

然后:

  • 使用 SQL Server CE,数据库损坏,需要手动修复
  • 使用 MySQL,mysqld 守护进程已终止,需要重新启动

我们一直在通过 ANTS Memory Profiler(使用 SQL CE 配置)监控应用程序内存使用情况,但令我们惊讶的是,应用程序“私有字节”似乎根本没有增加——ANTS 和资源经理

尽管如此,当应用程序被强制关闭时(在出现此类错误之后),任务管理器中的“物理内存使用率”从大约 80% 下降到 20-30%,并且我再次能够启动其他进程而无需获得另一个内存不足异常。

做了一些研究,我发现了这个:

什么是私有字节、虚拟字节、工作集?

我引用了关于私有字节的最后一部分:

Private Bytes 是可执行文件正在使用的内存量的合理近似值,可用于帮助缩小内存泄漏的潜在候选者列表;如果您看到这个数字不断增长且无休止地增长,您会想要检查该过程是否存在泄漏。但是,这不能证明存在或不存在泄漏。

考虑到链接主题的其余部分,据我所知,“私有字节”可能包含也可能不包含链接的非托管 dll 分配的内存,因此:

我将 ANTS 配置为还报告有关非托管内存的信息(按模块部分划分的非托管内存细分),我注意到以下 2 个模块之一(取决于特定的 sessionfactory 设置)占用越来越多的空间(具有兼容的比率大约一周后计算机内存不足)

  1. sqlceqp35
  2. MSVCR120

鉴于目前的结果,我计划进行以下测试:

  1. 更新休眠版本
  2. 试图进一步分析当前的 nhibernate sessionhelper 配置
  3. 创建一个没有 WPF 用户界面的空控制台应用程序(是的,此应用程序使用 WPF)我在其中放置了越来越多的代码,直到我能够重现该问题

有什么建议吗?

编辑 2016 年 6 月 30 日:

这是会话工厂初始化:

SESSION FACTORY:(自定义驱动是为了避免在 4000 字符后截断)

factory = Fluently.Configure()
                        .Database(MsSqlCeConfiguration.Standard.ConnectionString(connString)
                            .ShowSql()
                            .MaxFetchDepth(3)
                            .Driver<MySqlServerCeDriver>())     // FIX truncation 4000 chars
                        .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
                        .ProxyFactoryFactory<NHibernate.ByteCode.LinFu.ProxyFactoryFactory>()
                        .ExposeConfiguration(c =>
                        {
                            c.SetProperty("cache.provider_class", "NHibernate.Cache.HashtableCacheProvider");
                            c.SetProperty("cache.use_query_cache", "true");
                            c.SetProperty("command_timeout", "120");
                        })
                        .BuildSessionFactory();

    public class MySqlServerCeDriver : SqlServerCeDriver
    {
        protected override void InitializeParameter(
            IDbDataParameter dbParam,
            string name,
            SqlType sqlType)
        {
            base.InitializeParameter(dbParam, name, sqlType);

            if (sqlType is StringClobSqlType)
            {
                var parameter = (SqlCeParameter)dbParam;
                parameter.SqlDbType = SqlDbType.NText;
            }
        }
    }

编辑 07/07/2016

根据要求,GetSession() 执行以下操作:

public static ISession GetSession()
        {
            ISession session = factory.OpenSession();
            session.FlushMode = FlushMode.Commit;

            return session;
        }
4

0 回答 0