首页 > ODOO > 正文

Odoo 系统变慢怎么办?workers 调优与瓶颈排查实操

fenij 2026-08-05 3 ODOO

Odoo 用着用着就卡:点个菜单转圈五六秒,做批量导入直接超时,一到早上大家同时上线就集体变慢。很多人第一反应是加内存加 CPU,但硬件加上去往往没什么变化——因为默认配置下 Odoo 只跑在单进程多线程模式,压根用不满多核。真正要动的是 workers。

先分清是应用慢还是数据库慢

盲目调参最浪费时间。先看两个地方。

服务器上执行 top,看 odoo 进程的 CPU 占用。如果单个 odoo 进程长期贴着 100%(也就是跑满一个核),其他核基本闲着,那就是典型的没开 workers。

再看 PostgreSQL 那边。装上 pg_stat_statements 之后跑一句:

SELECT query, calls, mean_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC LIMIT 10;

如果排在前面的语句平均耗时上百毫秒,问题在数据库,调 workers 帮助有限。两边都要看一眼再决定动哪里。

workers 到底该设多少

官方推荐的算法是 workers = CPU核数 × 2 + 1。4 核就是 9,8 核就是 17。但这只是上限参考,内存才是真正的约束条件——每个 worker 大约吃 300MB 到 1GB,模块装得越多吃得越狠。

我一般这么估:可用内存除以 800MB,和 核数 × 2 + 1 取小的那个。一台 4 核 8G 的机器,PostgreSQL 要留 2G,Odoo 能用 5G 左右,那 workers 设 6 就比设 9 稳。

还有一条容易被忽略:一个 worker 大概能扛 6 个并发请求。60 人同时在线、每人平均 10% 时间在发请求,6 个 worker 就够了,不用堆到十几个。

改 odoo.conf

配置文件通常在 /etc/odoo/odoo.conf/etc/odoo-server.conf。关键几项:

[options]
workers = 6
max_cron_threads = 2
limit_memory_soft = 2147483648
limit_memory_hard = 2684354560
limit_time_cpu = 600
limit_time_real = 1200
limit_request = 8192
db_maxconn = 64

逐条说明:limit_memory_soft 是软上限(这里 2GB),worker 超过之后会在处理完当前请求后自杀重启,不影响用户;limit_memory_hard 是硬上限,直接 kill,所以要比 soft 大 20% 左右。limit_time_real 是单个请求墙钟时间上限,做大批量导入的话调到 1200 秒比较安全。max_cron_threads 一定要大于 0,否则开了 workers 之后定时任务不会跑。

改完重启:

systemctl restart odoo
ps aux | grep odoo | wc -l

进程数应该变成 workers + cron 线程 + 1 个主进程。

别忘了改反向代理超时

这是最常见的翻车点:Odoo 那边 limit_time_real 设了 1200,Nginx 还是默认 60 秒,结果导入到一半浏览器报 504,实际后台还在跑。Nginx 里要同步放宽:

proxy_read_timeout 1800;
proxy_connect_timeout 1800;
proxy_send_timeout 1800;
client_max_body_size 100M;

原则很简单,代理的超时必须大于 Odoo 的 limit_time_real

数据库和存储这边也要收拾

PostgreSQL 的默认配置是给小机器用的,八成没改过。shared_buffers 设成物理内存的 25%,effective_cache_size 设 50%~75%,work_mem 给 16MB 到 64MB。改完 systemctl restart postgresql

另外两件事收益很直接。一是附件别存数据库,在 Odoo 的系统参数里把 ir_attachment.location 设成 file:///,几万张产品图存在库里会让备份和查询同时变慢。二是定期清历史数据,mail_messagemail_tracking_valueir_logging 这三张表长得最快,跑一年下来几百万行很正常。清完记得:

VACUUM ANALYZE;

常见问题

问:开了 workers 之后定时任务全不跑了?
检查 max_cron_threads 是不是 0。多进程模式下 cron 由独立线程处理,设成 0 等于关掉。设 1 或 2 就行,别设太大,会抢数据库连接。

问:worker 频繁重启,日志里一堆 memory limit 提示?
说明 limit_memory_soft 给小了,或者某个自定义模块有内存泄漏。先把 soft 提到 2.5GB 观察,还是频繁的话用 --log-level=debug 定位是哪个模型的操作触发的。

问:workers 设成 0 和设成 1 有什么区别?
0 是多线程模式,适合开发调试和长连接;1 是多进程模式但只有一个 worker,并发能力还不如 0。生产环境要么 0 要么大于等于 3,别停在 1。

你们 Odoo 跑在什么配置上、workers 设了多少、调完提升多少,欢迎到 fenij.com 留言交流,我这边也在持续攒各种规模下的参数样本。