首页 > 解决方案 > 在底层 C 驱动程序中执行许多插入和捕获异常时,mongocxx 崩溃

问题描述

我有一个 C++ 应用程序,它正在处理 JSON 并插入数据库。它正在做一个非常简单的插入,解析 JSON 添加几个字段并插入如下。

我还用 try/catch 包围了调用,以处理可能引发的任何异常。

该应用程序可能每分钟处理大约 360-400 条记录。

它一直运行良好,但偶尔会出错和崩溃。下面的代码和堆栈跟踪。

代码

try {
    bsoncxx::builder::basic::document builder;
    builder.append(bsoncxx::builder::basic::concatenate(bsoncxx::from_json(jsonString)));
    builder.append(bsoncxx::builder::basic::kvp(std::string("created"), bsoncxx::types::b_date(std::chrono::system_clock::now())));

    bsoncxx::document::value doc = builder.extract();

    bsoncxx::stdx::optional<mongocxx::result::insert_one> result = m_client[m_dbName][std::string("Data")].insert_one(doc.view());

    if (!result) {
        m_log->warn(std::string("Insert failed."), label);
    }
} catch (...) {
    m_log->warn(std::string("Insert failed and threw exception."), label);
}

堆栈跟踪

所以我想我有两个问题。关于它为什么崩溃的任何想法?是否有某种方法可以捕获并处理此错误,从而使应用程序崩溃。

mongocxx 版本是:3.3.0

mongo-c 版本为:1.12.0

任何帮助表示赞赏。

更新 1 我对数据库进行了一些分析,尽管它在执行大量写入时执行得非常好,并且所有操作都使用索引。大多数低效操作需要 120 毫秒,所以我认为这不是性能问题。

更新 2 使用 valgrind 进行分析后,我找不到任何分配错误。然后我使用 perf 来分析 CPU 使用率,并发现随着时间的推移 CPU 使用率会增加。通常在进程首次启动时从大约 15% 的基本负载开始,然后在 4 或 5 小时的过程中逐渐上升,直到 CPU 使用率约为 40 - 50% 时发生崩溃。在这整个时间内,每秒数据库操作的数量保持在每秒 10 次。

为了排除其他处理代码导致此问题的可能性,我删除了所有数据库处理并在夜间运行进程,CPU 使用率始终保持在 15% 的水平。

我正在尝试其他一些策略来尝试找出根本原因。如果我发现任何东西会更新。

更新 3 我相信我已经发现了这个问题的原因。在插入过程之后,还有一个更新,它使用 $push 运算符将两个项目推送到一个数组中。在关闭该文档之前,它会针对不同的记录执行此操作多达 18,000 次。在高 CPU 负载下它在插入上崩溃的事实有点像红鲱鱼。

CPU 使用率的增加是该进程需要更长的时间来执行,因为文档中的数组被推送到更长的时间。我重新设计使用 Redis,并且只有在收到所有要推送到数组的项目后才插入到 mongodb。这个扁平的 CPU 使用率。解决此问题的另一种方法可能是将每个项目插入到临时集合中,并在收到所有要推送的项目后,使用 $push 聚合来编译带有数组的单个记录。

下图说明了在文档上使用 $push 时数组变长的问题。巨大的下降是在收到所有记录并为下一组项目创建新文档时。

CPU使用率 操作执行时间

在结束这个问题时,我将查看 MongoDB Jira,看看是否有人使用 $push 运算符报告了这个问题,如果没有自己报告,以防万一这在未来的版本中可以改进。

标签: mongodbmongo-cxx-drivermongo-c-driver

解决方案


推荐阅读