邮政管理员使用过多的CPU和磁盘写入


9

使用PostgreSQL 9.1.2

我看到过多的CPU使用率以及来自邮局主管任务的大量磁盘写操作。即使我的应用程序几乎什么也不做(每分钟10次插入),也会发生这种情况。但是,有相当数量的连接打开。

我一直在尝试确定导致应用程序崩溃的原因。我对Postgresql相当陌生,到目前为止还没有到位。我在配置文件中打开了一些日志记录选项,并查看了pg_stat_activity表中的连接,但是它们都处于空闲状态。但是,每个连接消耗约50%的CPU,并且正在以每秒15M / s的速度向磁盘写入数据(不读取内容)。

我基本上是通过很少的调整来使用stock postgresql.conf。我将不胜感激,对我可以做些什么来寻求帮助。

这是top / iotop向我显示的示例:

Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                          
17057 postgres  20   0  236m  33m  13m R 45.0  0.1  73:48.78 postmaster                                                                                                                       
17188 postgres  20   0  219m  15m  11m R 42.3  0.0  61:45.57 postmaster                                                                                                                       
17963 postgres  20   0  219m  16m  11m R 42.3  0.1  27:15.01 postmaster                                                                                                                       
17084 postgres  20   0  219m  15m  11m S 41.7  0.0  63:13.64 postmaster                                                                                                                       
17964 postgres  20   0  219m  17m  12m R 41.7  0.1  27:23.28 postmaster                                                                                                                       
18688 postgres  20   0  219m  15m  11m R 41.3  0.0  63:46.81 postmaster                                                                                                                       
17088 postgres  20   0  226m  24m  12m R 41.0  0.1  64:39.63 postmaster                                                                                                                       
24767 postgres  20   0  219m  17m  12m R 41.0  0.1  24:39.24 postmaster                                                                                                                       
18660 postgres  20   0  219m  14m 9.9m S 40.7  0.0  60:51.52 postmaster                                                                                                                       
18664 postgres  20   0  218m  15m  11m S 40.7  0.0  61:39.61 postmaster                                                                                                                       
17962 postgres  20   0  222m  19m  11m S 40.3  0.1  11:48.79 postmaster                                                                                                                       
18671 postgres  20   0  219m  14m   9m S 39.4  0.0  60:53.21 postmaster                                                                                                                       
26168 postgres  20   0  219m  15m  10m S 38.4  0.0  59:04.55 postmaster  


Total DISK READ: 0.00 B/s | Total DISK WRITE: 195.97 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                        
17962 be/4 postgres    0.00 B/s   14.83 M/s  0.00 %  0.25 % postgres: aggw aggw [local] idle
17084 be/4 postgres    0.00 B/s   15.53 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17963 be/4 postgres    0.00 B/s   15.00 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17188 be/4 postgres    0.00 B/s   14.80 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
17964 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.24 % postgres: aggw aggw [local] idle
18664 be/4 postgres    0.00 B/s   15.13 M/s  0.00 %  0.23 % postgres: aggw aggw [local] idle
17088 be/4 postgres    0.00 B/s   14.71 M/s  0.00 %  0.13 % postgres: aggw aggw [local] idle
18688 be/4 postgres    0.00 B/s   14.72 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
24767 be/4 postgres    0.00 B/s   14.93 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18671 be/4 postgres    0.00 B/s   16.14 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
17057 be/4 postgres    0.00 B/s   13.58 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
26168 be/4 postgres    0.00 B/s   15.50 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle
18660 be/4 postgres    0.00 B/s   15.85 M/s  0.00 %  0.00 % postgres: aggw aggw [local] idle

更新:很多文件写入似乎是对$ PG_DATA / base /目录中的一些临时(?)文件的。我对这里的文件结构的理解是,每个表基本上都存储为一个文件,该文件的名称是表的OID。但是,有大量名为的文件tnn_nnnnnnn,并且这些文件似乎一直在不断写入(也许被覆盖)。这些文件是做什么用的?文件约有4700个,大小均为8K:

-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t12_1430975
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t16_1432736
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439066
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436243
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t24_1436210
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t19_1393372
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t28_1439051
-rw-------. 1 postgres postgres     8192 Jul  3 23:08 t8_1430334

更新:在postmaster进程上运行strace基本上会显示很多文件I / O内容:

open("base/16388/t24_1435947_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
ftruncate(9, 0)                         = 0
lseek(9, 0, SEEK_END)                   = 0
open("base/16388/t24_1435941", O_RDWR)  = 18
lseek(18, 0, SEEK_END)                  = 0
write(9, "\0\0\0\0\0\0\0\0\1\0\0\0000\0\360\37\360\37\4 \0\0\0\0b1\5\0\2\0\0\0"..., 8192) = 8192
lseek(18, 0, SEEK_END)                  = 0
close(9)                                = 0
open("base/16388/t24_1435947", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 8192
close(18)                               = 0
close(9)                                = 0
open("base/16388/t24_1435944_fsm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944_vm", O_RDWR) = -1 ENOENT (No such file or directory)
open("base/16388/t24_1435944", O_RDWR)  = 9
lseek(9, 0, SEEK_END)                   = 0
close(9)                                = 0

更新:因此,这个问题似乎与临时表有关。我们更改了设置,使临时表成为“常规”表,所有磁盘活动都消失了,性能又回到了我期望的水平。现在,此更改只是一个快速而肮脏的测试:如果我们真的要更改为使用常规表,则我们在并发和清理方面会遇到问题。临时桌子真的那么邪恶吗?还是我们在滥用它们?

更新:更多背景信息。我正在使用内部开发的基于语句的复制中间件。它已经相当成熟,并且已经使用MySQL多年,已经在许多项目中使用。过去一两年,我们仅使用PostgreSQL。实际上,我们将临时表用作复制机制的一部分。每当建立新连接时,我们都会为数据库中的每个表创建一个临时表。使用10-20个(长寿命)连接和约50个表,这可能会导致大量临时表。所有临时表都使用以下命令创建:

CREATE TEMPORARY TABLE... ON COMMIT DELETE ROWS;

临时表的语义非常适合我们的复制方案,并且简化了许多我们必须用于MySQL的代码,但是看起来实现也不公平。从我所做的研究来看,我认为临时表并不是真正用于我们使用它们的功能。

我不是该主题的内部专家(甚至不是亲密的专家),只是该主题的使用者,所以我的解释可能不是100%准确,但我认为这很接近。


3
您的理解有些过时,如果查看官方文档,您会发现“ ...对于临时关系,文件名的格式为tBBB_FFF,其中BBB是创建文件的后端的后端ID。 ,而FFF是文件节点号。...”
Milen A. Radev 2012年

哇,那是一个性能出色的磁盘I / O子系统。strace关于工人实际在做什么?
womble

@ MilenA.Radev,所以看起来我可能对临时表做了一些奇怪/过多的事情。这是有趣的。我确实有很多使用临时表的触发器。我会仔细看这些。
wolfcastle,2012年

@womble,我已经用strace的输出更新了问题。
wolfcastle,2012年

您实际上遇到性能问题吗?
voretaq7'8

Answers:


1

您的PostgreSQL配置不完善。从您最初的帖子来看,这令人怀疑,

 Cpu(s): 18.9%us, 14.4%sy,  0.0%ni, 53.4%id, 11.8%wa,  0.0%hi,  1.5%si,  0.0%st
 Mem:  32865916k total,  7263720k used, 25602196k free,   575608k buffers
 Swap: 16777208k total,        0k used, 16777208k free,  4464212k cached

服务器上的32GB空间中,约有25GB是免费的,不包括约575MB的缓冲区。

在您的postgresql.conf文件中,

 shared_buffers = 32MB                   # min 128kB                               
 #temp_buffers = 8MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 #work_mem = 1MB                         # min 64kB
 #maintenance_work_mem = 16MB            # min 1MB
 #max_stack_depth = 2MB   

我假设这是一个专用的数据库。如果是这样,请将其更改为以下参数并重新加载/重新启动,

 shared_buffers = 16GB                   # min 128kB                               
 temp_buffers = 128MB                     # min 800kB
 #max_prepared_transactions = 0          # zero disables the feature
 ...
 work_mem = 8MB                         # min 64kB
 maintenance_work_mem = 64MB            # min 1MB
 max_stack_depth = 4MB   

让我知道这如何改变您的表现,并可以根据需要对其进行进一步调整。

关于未记录的表,如果您的临时表包含临时的临时数据,并且如您所述,是在会话上创建的,则最好使用未记录的表。

如果可以的话,您可以截断会话后的表。

此处的更多信息-http: //michael.otacoo.com/postgresql-2/unlogged-table-performance-in-postgresql-9-1/

我不确定为什么需要临时表进行复制。您不能使用PostgreSQL流复制吗?


0

如果您的服务器不准备使用临时表并具有长期连接(可能涉及连接池),则可能会成为负担。您可以尝试使用的一个PostgreSQL参数是temp_buffers控制分配给临时表的RAM。这些临时缓冲区是为每个连接分配的,对于您的站点,默认值(8MB)可能太低。

也许您还需要更改客户端应用程序的某些行为,具体取决于您使用临时表的方式。在Stack Overflow上有一个类似的问题,给出了很好的答案


我将不得不问我的内部专家我们是否尝试过调整temp_buffers值(我们尝试了很多不同的方法)。您所指出的问题实际上并不适用,因为我们不是以这种方式使用临时表。我已用更多详细信息更新了该问题。
wolfcastle,2012年

感谢您对问题的更新和postgresql.conf文件,这是我们需要尝试改善这种情况的方法。我同意@Chida的回答,这与我建议的wrt一致temp_buffers。您还能告诉我们您要复制的数据库的大小吗?多少张表,每张表的平均大小和数据库的总大小?
托宁2012年

0

您可以发布postgresql.conf文件吗?您的postgresql似乎已大大优化。

您还可以发布:

  • 如果您将未记录的表用于临时表?

  • 多少磁盘以及采用哪种RAID配置?


我把postgresql.conf文件放在这里。我相信您不能创建一个既临时又未记录的表。RAID 1 + 0(总存储空间为3TB)中有6个1TB磁盘
wolfcastle,2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.