我们有一个运行在Postgresql 9.5上的CentOS release 6.5 (Final)服务器有16 of的内存。我们正在运行一个长事务,它在多个表中添加和更新数百万行中的10s行。除了这个事务,在这个阶段没有查询在DB上运行,但是它可以在其他查询期间运行,所以必须进行事务处理。
它可以正常工作,直到OOM杀手决定它已经足够并杀死postmaster进程为止:
Out of memory: Kill process 1766 (postmaster) score 890 or sacrifice child
Killed process 1766, UID 26, (postmaster) total-vm:24384508kB, anon-rss:14376288kB, file-rss:138616kB以下是相关的postgres配置:
#-------------------------------------------------------------------------
# RESOURCE USAGE (except WAL)
#-------------------------------------------------------------------------
# - Memory -
shared_buffers = 128MB # min 128kB
# (change requires restart)
#huge_pages = try # on, off, or try
# (change requires restart)
#temp_buffers = 8MB # min 800kB
#max_prepared_transactions = 0 # zero disables the feature
# (change requires restart)
# Caution: it is not advisable to set max_prepared_transactions nonzero unless
# you actively intend to use prepared transactions.
#work_mem = 4MB # min 64kB
#maintenance_work_mem = 64MB # min 1MB
#autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem
#max_stack_depth = 2MB # min 100kB
dynamic_shared_memory_type = posix # the default is the first option
# supported by the operating system:
# posix
# sysv
# windows
# mmap
# use none to disable dynamic shared memory
# - Disk -
#temp_file_limit = -1 # limits per-session temp file space
# in kB, or -1 for no limit
# - Kernel Resource Usage -
#max_files_per_process = 1000 # min 25
# (change requires restart)
#shared_preload_libraries = '' # (change requires restart)
# - Cost-Based Vacuum Delay -
#vacuum_cost_delay = 0 # 0-100 milliseconds
#vacuum_cost_page_hit = 1 # 0-10000 credits
#vacuum_cost_page_miss = 10 # 0-10000 credits
#vacuum_cost_page_dirty = 20 # 0-10000 credits
#vacuum_cost_limit = 200 # 1-10000 credits
# - Background Writer -
#bgwriter_delay = 200ms # 10-10000ms between rounds
#bgwriter_lru_maxpages = 100 # 0-1000 max buffers written/round
#bgwriter_lru_multiplier = 2.0 # 0-10.0 multipler on buffers scanned/round
# - Asynchronous Behavior -
#effective_io_concurrency = 1 # 1-1000; 0 disables prefetching
#max_worker_processes = 8另外,vm.overcommit_memory被设置为2
我发现的一个解决方案是禁用OOM杀手的特定过程,我试图避免,因为它让我觉得不是正确的解决方案。我没有找到任何方法来强迫postgres将内存刷新到磁盘,或者限制使用的内存总量。
有什么建议吗?
发布于 2018-05-13 06:24:59
好的,在尝试了很多事情之后,我找到了解决办法。
这个问题隐藏在我们对JDBC库的使用中。
我们与设置为false的自动提交有很长的连接:
connection.setAutoCommit(false)在此期间,我们使用游标执行了许多小查询和几个查询:
statement.setFetchSize(SOME_FETCH_SIZE)在JDBC中,您可以创建一个connection对象,并通过这个连接创建statements。当您执行状态时,您将得到一个result set。
现在,这些对象中的每一个都需要关闭,但是如果关闭语句,则条目集将关闭,如果关闭连接,则关闭所有语句及其结果集。
我们习惯于用自己的连接来缩短活的查询,因此我们从不关闭语句,假设连接一旦关闭就会处理这些事情。
现在的问题是,这个长事务(大约24小时)从未关闭连接。这些陈述从未结束。显然,语句对象包含运行代码的服务器和PostgreSQL数据库上的资源。
对于DB中剩下的资源,我最好的猜测是与游标相关的内容。使用游标的语句从未关闭,因此它们返回的结果集也从未关闭。这意味着数据库没有释放DB中的相关游标资源,而且由于它位于一个巨大的表上,因此占用了大量的RAM。
我唯一不明白的是,当PostgreSQL未能分配内存时,它为什么没有保存磁盘上的一些资源(而不是交换)。
希望它能帮助将来有类似问题的人。
发布于 2018-05-11 07:19:56
确保您有足够的交换空间空闲,并禁用OOM杀手。它是为一个用例设计的,而不是你正在做的事情。除非有什么地方可以交换,否则Linux不能安全地过度提交。还要检查内核参数vm.swappiness,它设置为什么?
https://dba.stackexchange.com/questions/206448
复制相似问题