You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向Odoo导入海量数据时的服务器超时问题

Odoo批量导入数据触发实时限制的解决方案

问题核心

从外部API获取73076条完整数据后,通过request.env[MODEL].sudo().create()仅能创建约18538条记录,剩余数据因Odoo触发**服务器虚拟实时限制(limit_time_real)**失败。调整Odoo内存/时间配置、PostgreSQL参数、拆分路由批次均未解决问题。

关键原因分析

  1. create()方法会为每条记录触发完整的模型生命周期(字段计算、触发器、约束校验等),批量处理时资源占用累积过快,超出实时限制。
  2. 拆分路由若未实现完全独立的请求/事务隔离,仍会在同一worker进程内累积内存占用,无法彻底规避限制。
  3. 未正确释放Odoo环境缓存、未及时提交事务,导致内存泄漏持续增加。

具体解决方案

1. 替换create()为load()批量导入(最优方案)

Odoo内置的BaseModel.load()方法专为批量导入设计,通过直接生成SQL插入语句、跳过部分模型生命周期逻辑,大幅降低资源占用与耗时:

@http.route('/import/batch-data', type='http', auth='user', methods=['POST'])
def import_batch_data(self, **kwargs):
    # 从外部API获取完整数据列表
    data_list = self._fetch_external_api_data()
    model = request.env['your.model.name'].sudo()
    
    # 定义字段映射(需与模型字段名完全匹配)
    fields = list(data_list[0].keys())
    # 转换数据格式:二维数组,每个子数组对应一条记录的字段值
    values = [list(item.values()) for item in data_list]
    
    # 执行批量导入
    import_result = model.load(fields, values)
    
    # 处理导入结果
    if import_result['ids']:
        return json.dumps({
            'status': 'success',
            'created_count': len(import_result['ids']),
            'failed_count': len(import_result['messages'])
        })
    else:
        return json.dumps({
            'status': 'failed',
            'errors': import_result['messages']
        })

2. 优化批次处理逻辑(若需保留create())

若必须使用create(),需严格控制批次大小,并在每个批次后提交事务、清除环境缓存,彻底释放资源:

@http.route('/import/data-by-batch', type='http', auth='user', methods=['POST'])
def import_data_by_batch(self, **kwargs):
    data_list = self._fetch_external_api_data()
    model = request.env['your.model.name'].sudo()
    batch_size = 1000  # 根据服务器配置调整,建议500-2000条/批次
    total_count = len(data_list)
    created_count = 0
    
    for i in range(0, total_count, batch_size):
        batch_data = data_list[i:i+batch_size]
        # 创建当前批次记录
        model.create(batch_data)
        created_count += len(batch_data)
        
        # 提交事务并清除环境缓存,释放内存
        request.env.cr.commit()
        request.env.clear()
    
    return json.dumps({
        'status': 'success',
        'total_count': total_count,
        'created_count': created_count
    })

3. 彻底隔离批次请求(拆分路由的正确姿势)

若采用多路由拆分,需确保每个批次为独立HTTP请求(而非同一请求内调用多个路由):

  • 前端按批次分多次调用导入接口,每次传入批次起始/结束索引
  • 后端接口仅处理当前批次数据,处理完成后立即释放资源

4. 调整Odoo与PostgreSQL核心配置

Odoo配置(odoo.conf)

# 增大实时超时时间(单位:秒,建议设为3600即1小时)
limit_time_real = 3600
# 增大软/硬内存限制(根据服务器内存调整,如8G)
limit_memory_soft = 8589934592
limit_memory_hard = 8589934592
# 增加worker数量(建议=2*CPU核心数+1)
workers = 5
# 调整worker超时时间
limit_time_cpu = 600

PostgreSQL配置(postgresql.conf)

# 增大单操作内存限制(建议64MB)
work_mem = 64MB
# 增大维护操作内存(建议2GB)
maintenance_work_mem = 2GB
# 增大WAL日志大小,减少切换频率
max_wal_size = 16GB
# 增大连接数(根据worker数量调整)
max_connections = 100

5. 临时禁用模型冗余逻辑

若模型包含大量计算字段、触发器或约束,可临时禁用以降低导入开销:

@http.route('/import/data-with-disabled-logic', type='http', auth='user')
def import_data_with_disabled_logic(self, **kwargs):
    model = request.env['your.model.name'].sudo()
    
    # 临时禁用计算字段方法
    original_compute = model._compute_some_field
    model._patch_method('_compute_some_field', lambda self: None)
    
    # 临时移除特定约束
    original_constraints = model._constraints
    model._constraints = [c for c in original_constraints if c[0] != '_check_some_constraint']
    
    try:
        # 执行批量导入逻辑(参考方案1或2)
        data_list = self._fetch_external_api_data()
        # ... 导入代码 ...
    finally:
        # 恢复原逻辑
        model._revert_method('_compute_some_field')
        model._constraints = original_constraints
    
    return json.dumps({'status': 'success'})

内容的提问来源于stack exchange,提问作者Andromeda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:13:12