谈谈DB2的db2fmp进程
说起这个db2fmp进程,百度,google上那可是铺天盖地的文章,总结起来,都是在讨论如下四个问题:
- db2fmp进程是什么
- 为什么db2fmp占用了这么多内存
- 为什么db2fmp占用了这么多CPU
- 为什么我的db2diag日志里这么多关于db2fmp的错误和警告日志信息
下面我们就来回答这些问题。首先要解释下db2fmp是干什么用的。
一. 什么是db2fmp
定义: db2fmp是圈围模式的进程,它主要负责执行外部存储过程和用户自定义函数。
大家都知道存储过程和自定义函数我们统一叫做routines, 而routine又分为external和SQL两种,external是用Java或者C编写的,而SQL rountine是直接用SQL编写的。
现在大家都知道了原来db2fenc是用来运行咱们用Java/C等非SQL语言写的存储过程和自定义函数的。
我们先来看下db2fmp在db2进程模型中的位置:
、
大家可以看到db2fmp不属于DB2的核心进程,是运行在DB2内部防火墙之外的。其实这个很好理解啦。咱们用户自己用Java/C写的东西,DB2是没有办法信任你的。天知道代码写的有多乱,为了安全DB2绝对不会让他们运行于自己的内存空间。 就比如你绝对不会留一个不知底细的陌生人在自己家里住宿,但是发善心做好事让他住外面的车库是可以的。
正因为运行在db2fmp的程序都是些不知底细的家伙,所以他们经常捣乱,一会把内存用没了,一会把CPU用没了。带来了上面说的种种问题。那么我们如何来监控db2fmp到底干了什么呢?
二.如何监控db2fmp
1.使用db2pd -dbptnmem 来监控FMP用了多少内存
主要查看FMP_RESOURCES占用了多少内存
$ db2pd -dbptnmem
Database Member 0 -- Active -- Up 9 days 21:04:07 -- Date 2017-05-03-23.48.11.749632
Database Member Memory Controller Statistics
Controller Automatic: Y
Memory Limit: 249454204 KB
Current usage: 206569216 KB
HWM usage: 208253056 KB
Cached memory: 16285312 KB
Individual Memory Consumers:
Name Mem Used (KB) HWM Used (KB) Cached (KB)
========================================================
APPL-XXXXXXXX 342336 1399232 58944
DBMS-XXXXXXXX 376448 376448 77952
FMP_RESOURCES 22528 22528 0
2.使用db2pd -fmp
主要查看ActiveThrd和PooledThrd的个数
$ db2pd -fmp
Database Member 0 -- Active -- Up 9 days 21:38:06 -- Date 2017-05-04-00.22.10.091912
FMP:
Pool Size: 4
Max Pool Size: 1041 ( Automatic )
Keep FMP: YES
Initialized: YES
Trusted Path: /home/a1insctp/sqllib/function/unfenced
Fenced User: db2fenc1
Shared Memory: 0x0780000000DF0420
IPC Pool: 0x0780000000DF0480
FMP Process:
Address FmpPid Bit Flags ActiveThrd PooledThrd ForcedThrd Active IPCList
0x0780000000E2CA20 22872258 64 0x00000000 0 0 0 No 0x0780000000E2C120
Active Threads:
Address FmpPid EduPid ThreadId
No active threads.
Pooled Threads:
Address FmpPid ThreadId
No pooled threads.
Forced Threads:
Address FmpPid ThreadId
No forced threads.
FMP Process:
Address FmpPid Bit Flags ActiveThrd PooledThrd ForcedThrd Active IPCList
0x0780000000E254E0 22020206 64 0x00000002 0 1 0 Yes 0x07800000030EFFC0
3. 使用ps aux来查看每个db2fmp的内存使用量,查看CPU和内存变化的趋势
$ ps aux | more
USER PID %CPU %MEM SZ RSS TTY STAT STIME TIME COMMAND
db2fenc1 29884584 0.0 0.0 154916 154956 - A 09:17:47 12:11 db2fmp
db2fenc1 22020206 0.0 0.0 10788 10828 - A 09:20:07 0:02 db2fmp
db2fenc1 22872258 0.0 0.0 2584 2624 - A 10:00:01 0:00 db2fmp
三. 如何解决db2fmp带来的内存和CPU的问题。
1. 杀掉db2fmp进程。
当我们发现db2fmp里面运行的rountine越来越慢,db2fmp占用的内存越来高的时候,我们需要kill掉占用SZ内存比较多的(一般是超过100M)的db2fmp了。kill 掉 db2fmp对于db2本身来说没有任何问题,需要评估db2fmp里面运行的routines被kill掉是否会打来问题。两种方法来kill
- kill -9 <processid_db2fmp>
- db2fmpterm <processid_db2fmp>
2. 设置KEEPFENCED 数据库管理器参数为NO。
此参数控制db2fmp是否可以被复用,如果设置为NO, 就是不可以被复用,那么每次调用都会重新生成一个db2fmp进程,调用结束后都会删除。这样可以避免累积的内存泄漏,但是如果我们经常频繁掉用external rountines,会带来性能问题。
3. 设置DB2_MAX_THREADS_PER_FMP参数
此参数是DB2内部参数,DB2 Knowledge Center里面都没有此参数的任何信息。通过此参数可以控制在一个db2fmp里最多运行的线程数,如果我们通过db2pd -fmp发现db2fmp内运行的线程过多的话,可以设置此参数为一个合适的值。 当db2fmp内运行的的线程到达此值后,数据库会再起一个新的db2fmp进程。
4.设置FENCED_POOL,NUM_INITFENCED参数
一般来说 我们都设置FENCED_POOL为automatic,如果有特殊需要我们也可以设置为固定值,此参数用于控制db2fmp的最大进程数量
5. 重新审查和优化External routines的代码
6. 如果可能,使用SQL rountines 替代 External Routines, 相信我,使用例如Java存储过程之类的外部存储过程只会给你的数据库增加维护成本和无休止的麻烦。能不用坚决不 用,能改写坚决改写。
7. 写一个小程序,定时kill掉db2fmp进程,这样让db2fmp轻装上阵工作。(也是walk around,非长久之计)。
下面是IBM官网关于db2fmp问题的汇总:
db2fmp memory issues:
http://www-01.ibm.com/support/docview.wss?uid=swg21412612
FAQ for db2fmp messages in db2diag:
http://www-01.ibm.com/support/docview.wss?uid=swg21470035
How to monitor db2fmp:
http://www-01.ibm.com/support/docview.wss?uid=swg21566971
Collecting Data for db2 stored procedure:
http://www-01.ibm.com/support/docview.wss?uid=swg21383251
Accumulation of db2fmp(java) process:
http://www-01.ibm.com/support/docview.wss?uid=swg21432402