分类: Mysql/postgreSQL
2017-01-05 17:01:00
数据库是比较重内存的应用软件之一,比如排序、聚合、使用较大的列、使用很长的SQL(值SQL本身的内容长度),或者传入很大的变长类型值时,都可能使得单个连接就会消耗很大的内存。
而另一方面,每个连接会消耗一定的内存,比如SYSCACHE , RELCACHE,随着访问的对象变多,如果是长连接,消耗的内存也会越多。 通常来说,长连接当访问了很多元数据时,可能占用几十MB到上百MB不等。
当使用了cgroup来限制数据库实例的总内存时,随着数据库占用的RSS部分的内存越来越多,如果数据库连接在申请内存时,超出了cgroup的限制,则连接可能被OOM掉。
当然,即使不使用cgroup,Linux也会根据内核的配置,以及用户申请内存的动作,当时的剩余内存等情况综合,发生OOM。
有几篇文章可以参考一下
《一个笛卡尔积的update from语句引发的(内存泄露?)问题》
《PostgreSQL relcache在长连接应用中的内存霸占"坑"》
《Linux page allocation failure 的问题处理 - lowmem_reserve_ratio》
当发生了OOM后,如何找到引起OOM的那个会话,他是罪魁祸首(指单个会话申请了过多的内存),还是压死骆驼的最后一根稻草(指连接数过多)呢?
数据库又是如何申请内存的呢?
简单讲一下rss和cache.
rss是程序申请的内存,不能被内核自动释放,由用户自己来管理它什么时候被释放。
cache,通常指缓存,比如文件系统的缓存,不由用户进程来管理,它可以被内核释放。
我们所指的内存不足,是指即使cache完全被释放,也无法分配足够的内存给用户请求。
在cgroup的memory子系统中,我们可以看到这两个部分,rss很多,cache很少时,就要注意了,可能会发生OOM。
# cat memory.stat cache 204800 rss 0 mapped_file 0 pgpgin 974906 pgpgout 974856 swap 0 inactive_anon 155648 active_anon 0 inactive_file 49152 active_file 0 unevictable 0 hierarchical_memory_limit 102400000 hierarchical_memsw_limit 102400000 total_cache 204800 total_rss 0 total_mapped_file 0 total_pgpgin 974906 total_pgpgout 974856 total_swap 0 total_inactive_anon 155648 total_active_anon 0 total_inactive_file 49152 total_active_file 0 total_unevictable 0
以PostgreSQL数据库为例,为了管理方便,pg使用统一的内存分配和释放API,便于管理,详见src/backend/utils/mmgr/mcxt.c。
用得比较多的比如palloc,它申请的内存某些时候可以自动被回收,比如事务结束,会话断开,QUERY结束时,使用palloc申请的某些内存,会自动被释放。