在使用急切加载的 findOne Sequelize 方法期间,Nodejs 堆内存不足

Posted

技术标签:

【中文标题】在使用急切加载的 findOne Sequelize 方法期间,Nodejs 堆内存不足【英文标题】:Nodejs heap out of memory during findOne Sequelize method with eager loading 【发布时间】:2021-12-29 16:27:06 【问题描述】:

我的 NodeJS 应用程序当前使用 Sequelize 对象来跨多个阶段工作。该对象是 Model.findOne 操作的结果,该操作包括其他几个模型,类似于普通 SQL 中的多个表的左连接。

transaction  = await Transaction.findOne(
            where: 
                id: transaction.id
            ,
            include: transactionIncludes //this includes other models such as client, orderDetail, orderLog, etc
        )
    
    return transaction

有时,我的应用程序可以很好地挂载这个事务对象。 但是,当我尝试对其进行扩展时,我经常会遇到这些 OOM 错误,例如:

<--- Last few GCs --->

[736:0x60632a0]    72273 ms: Mark-sweep (reduce) 2036.3 (2045.7) -> 2036.2 (2045.7) MB, 13.2 / 0.0 ms  (+ 0.1 ms in 4 steps since start of marking, biggest step 0.1 ms, walltime since start of marking 184 ms) (average mu = 0.943, current mu = 0.951) final[736:0x60632a0]    72342 ms: Mark-sweep (reduce) 2041.9 (2051.4) -> 2041.9 (2051.4) MB, 10.9 / 0.0 ms  (+ 0.5 ms in 4 steps since start of marking, biggest step 0.3 ms, walltime since start of marking 64 ms) (average mu = 0.931, current mu = 0.833) finali

<--- JS stacktrace --->

FATAL ERROR: Reached heap limit Allocation failed - javascript heap out of memory
 1: 0xb2c2b0 node::Abort() [node]
 2: 0xa4025c node::FatalError(char const*, char const*) [node]
 3: 0xd1d11e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xd1d497 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xed68f5  [node]
 6: 0xee7d3d v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 7: 0xee8bf7 v8::internal::Heap::FinalizeIncrementalMarkingIfComplete(v8::internal::GarbageCollectionReason) [node]
 8: 0xeec6b0 v8::internal::IncrementalMarkingJob::Task::RunInternal() [node]
 9: 0xddae0b non-virtual thunk to v8::internal::CancelableTask::Run() [node]
10: 0xb9a7f4 node::PerIsolatePlatformData::RunForegroundTask(std::unique_ptr<v8::Task, std::default_delete<v8::Task> >) [node]
11: 0xb9c669 node::PerIsolatePlatformData::FlushForegroundTasksInternal() [node]
12: 0x159d8a6  [node]
13: 0x15afe14  [node]
14: 0x159e1f8 uv_run [node]
15: 0xa65fe5 node::SpinEventLoop(node::Environment*) [node]
16: 0xb6ed86 node::NodeMainInstance::Run(node::EnvSerializeInfo const*) [node]
17: 0xaef83a node::Start(int, char**) [node]
18: 0x7f8cda3cb09b __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
19: 0xa62f6c  [node]
Aborted (core dumped)

转储的核心大约有 2 GB 的内存。 我想在不增加 RAM 的情况下解决这个问题。

编辑:有人要求我显示包含模型关联的内容,它们是:

[redacted]

【问题讨论】:

显示 transactionIncludes 以及所有模型如何相互关联。 你好,我已经更新了我的问题以包括模型关联。感谢您的关注。 你显示的是emissaoIncludes而不是transactionIncludes 我忘记更改 const 名称。这是正确的对象,抱歉。 我看不到transactionIncludes中使用的VooIncludes 【参考方案1】:

如果您在 Sequelize 查询中包含多个 hasMany 关联(在同一级别或嵌套级别),那么您需要为所有这些关联指明 separate: true,以便 Sequelize 将分别执行所有此类包含的查询避免重复记录:

export const transactionIncludes = [
    model: CartaoPagamentos, as: 'cartaopagamento', type: 'hasOne', foreignKey: 'transaction_id',
    model: Cliente, as: 'cliente', type: 'belongsTo', foreignKey: 'cliente_id',
    model: Fila, as: 'fila', type: 'hasOne', foreignKey: 'transaction_id',
    model: Voo, as: 'voo', type: 'hasMany', foreignKey: 'transaction_id', include: VooIncludes, separate: true , 
    model: Passageiros, as: 'passageiro', type: 'hasMany', foreignKey: 'transaction_id', separate: true ,
    model: Cartaomilhas, as: 'cartaomilha', type: 'hasOne', foreignKey: 'transaction_id',
    model: Robot, as: 'robot', type: 'belongsTo', foreignKey: 'robo_id',
];

另外请查看我的回答here(关于hasMany 的部分,以便更好地了解当您在没有separate: true 选项的Sequelize 查询中指出多个hasMany 时,幕后发生了什么。

【讨论】:

以上是关于在使用急切加载的 findOne Sequelize 方法期间,Nodejs 堆内存不足的主要内容,如果未能解决你的问题,请参考以下文章

何时在休眠中使用延迟加载/急切加载?

我可以同时使用急切和延迟加载吗?

Java 中的急切加载是啥?

左外连接导轨在 where 条件下具有急切加载

“过滤”急切加载的数据时出现问题

laravel eloquent - 在嵌套急切加载的关系上不使用