PostgreSQL缓慢的提交性能

我们在使用PostgreSQLconfiguration时遇到了一些问题。 经过一些基准testing后,我发现非常简单的查询花费了相当长的时间,经过进一步的检查,实际的COMMIT命令显得非常慢。

我使用下表进行了一个非常简单的testing:

CREATE TABLE test ( id serial primary key, foo varchar(16), ); 

打开所有语句的logging后,我运行了以下查询10000次:

 BEGIN; INSERT INTO test (a) VALUES ('bar'); COMMIT; 

BEGIN和INSERT完成时间<1ms,但COMMIT平均需要22ms才能完成。

在我自己的PC上运行相同的基准testing,速度慢得多,BEGIN和INSERT语句的平均值相同,但平均COMMIT约为0.4ms(快20倍)。

经过一番阅读,我尝试了pg_test_fsync工具来试图解决这个问题。 在服务器上,我得到了这些结果:

 $ ./pg_test_fsync -o 1024 1024 operations per test O_DIRECT supported on this platform for open_datasync and open_sync. Compare file sync methods using one 8kB write: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 14.875 ops/sec fdatasync 11.920 ops/sec fsync 30.524 ops/sec fsync_writethrough n/a open_sync 30.425 ops/sec Compare file sync methods using two 8kB writes: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 19.956 ops/sec fdatasync 23.299 ops/sec fsync 21.955 ops/sec fsync_writethrough n/a open_sync 3.619 ops/sec Compare open_sync with different write sizes: (This is designed to compare the cost of writing 16kB in different write open_sync sizes.) 16kB open_sync write 5.923 ops/sec 8kB open_sync writes 3.120 ops/sec 4kB open_sync writes 10.246 ops/sec 2kB open_sync writes 1.787 ops/sec 1kB open_sync writes 0.830 ops/sec Test if fsync on non-write file descriptor is honored: (If the times are similar, fsync() can sync data written on a different descriptor.) write, fsync, close 34.371 ops/sec write, close, fsync 36.527 ops/sec Non-Sync'ed 8kB writes: write 248302.619 ops/sec 

在我自己的PC上,我得到:

 $ ./pg_test_fsync -o 1024 1024 operations per test O_DIRECT supported on this platform for open_datasync and open_sync. Compare file sync methods using one 8kB write: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 69.862 ops/sec fdatasync 68.871 ops/sec fsync 34.593 ops/sec fsync_writethrough n/a open_sync 26.595 ops/sec Compare file sync methods using two 8kB writes: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 26.872 ops/sec fdatasync 59.056 ops/sec fsync 34.031 ops/sec fsync_writethrough n/a open_sync 17.284 ops/sec Compare open_sync with different write sizes: (This is designed to compare the cost of writing 16kB in different write open_sync sizes.) 16kB open_sync write 7.412 ops/sec 8kB open_sync writes 3.942 ops/sec 4kB open_sync writes 8.700 ops/sec 2kB open_sync writes 4.161 ops/sec 1kB open_sync writes 1.492 ops/sec Test if fsync on non-write file descriptor is honored: (If the times are similar, fsync() can sync data written on a different descriptor.) write, fsync, close 35.086 ops/sec write, close, fsync 34.043 ops/sec Non-Sync'ed 8kB writes: write 240544.985 ops/sec 

服务器的configuration:

 CPU: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz RAM: 32GB Disk: 2x 2TB SATA disk in Software RAID 1 

用于比较的机器是一个有16GB内存和普通SATA磁盘的i5(没有raid)。

更多信息:

  • 操作系统:Ubuntu服务器12.10
  • 内核:Linux … 3.5.0-22-generic#34-Ubuntu SMP星期二1月8日21:47:00 UTC 2013 x86_64 x86_64 x86_64 GNU / Linux
  • 软件RAID 1
  • 文件系统是ext4
  • 没有指定其他安装选项。
  • Postgres版本9.1
  • Linux mdadm RAID

dump2efs的输出:

 dumpe2fs 1.42.5 (29-Jul-2012) Filesystem volume name: <none> Last mounted on: / Filesystem UUID: 16e30b20-0531-4bcc-877a-818e1f5d5fb2 Filesystem magic number: 0xEF53 Filesystem revision #: 1 (dynamic) Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize Filesystem flags: signed_directory_hash Default mount options: (none) Filesystem state: clean Errors behavior: Continue Filesystem OS type: Linux Inode count: 182329344 Block count: 729289039 Reserved block count: 36464451 Free blocks: 609235080 Free inodes: 182228152 First block: 0 Block size: 4096 Fragment size: 4096 Reserved GDT blocks: 850 Blocks per group: 32768 Fragments per group: 32768 Inodes per group: 8192 Inode blocks per group: 256 RAID stride: 1 Flex block group size: 16 Filesystem created: Sat Jan 19 12:42:19 2013 Last mount time: Wed Jan 23 16:23:11 2013 Last write time: Sat Jan 19 12:46:13 2013 Mount count: 8 Maximum mount count: 30 Last checked: Sat Jan 19 12:42:19 2013 Check interval: 15552000 (6 months) Next check after: Thu Jul 18 13:42:19 2013 Lifetime writes: 257 GB Reserved blocks uid: 0 (user root) Reserved blocks gid: 0 (group root) First inode: 11 Inode size: 128 Journal inode: 8 First orphan inode: 17304375 Default directory hash: half_md4 Directory Hash Seed: a71fa518-7696-4a28-bd89-b21c10d4265b Journal backup: inode blocks Journal features: journal_incompat_revoke Journal size: 128M Journal length: 32768 Journal sequence: 0x000df5a4 Journal start: 31733 

Mdadm – 尾巴输出:

 /dev/md2: Version : 1.2 Creation Time : Sat Jan 19 12:42:05 2013 Raid Level : raid1 Array Size : 2917156159 (2782.02 GiB 2987.17 GB) Used Dev Size : 2917156159 (2782.02 GiB 2987.17 GB) Raid Devices : 2 Total Devices : 2 Persistence : Superblock is persistent Update Time : Fri Mar 22 11:16:45 2013 State : clean Active Devices : 2 Working Devices : 2 Failed Devices : 0 Spare Devices : 0 Name : rescue:2 UUID : d87b98e7:d584a4ed:5dac7907:ae5639b0 Events : 38 Number Major Minor RaidDevice State 0 8 3 0 active sync /dev/sda3 1 8 19 1 active sync /dev/sdb3 

更新2013-03-25 :我在两个磁盘上运行了一个很长的智能testing,没有发现任何问题。 这两个磁盘都来自希捷,型号:ST3000DM001-9YN166。

更新2013-03-27 :我在完全空闲的机器上运行了最新版本(9.2.3)的pg_test_fsync:

 $ ./pg_test_fsync -s 3 3 seconds per test O_DIRECT supported on this platform for open_datasync and open_sync. Compare file sync methods using one 8kB write: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 39.650 ops/sec fdatasync 34.283 ops/sec fsync 19.309 ops/sec fsync_writethrough n/a open_sync 55.271 ops/sec 

这比以前好一点,但还是很可悲。 两个磁盘上的分区是alignment的:

 $ sudo parted /dev/sdb unit s print Model: ATA ST3000DM001-9YN1 (scsi) Disk /dev/sdb: 5860533168s Sector size (logical/physical): 512B/4096B Partition Table: gpt Number Start End Size File system Name Flags 4 2048s 4095s 2048s bios_grub 1 4096s 25169919s 25165824s raid 2 25169920s 26218495s 1048576s raid 3 26218496s 5860533134s 5834314639s raid 

装载-v输出:

 $ mount -v | grep ^/dev/ /dev/md2 on / type ext4 (rw,noatime) /dev/md1 on /boot type ext3 (rw) 

md2设备正在用于testing。 去销毁交换分区,并在单独的磁盘上运行pg_test_fsync。

如果我分别在两个磁盘上运行pg_test_fsync,则性能大致相同,分区使用noatime挂载:

 $ pg_test_fsync/pg_test_fsync -s 3 3 seconds per test O_DIRECT supported on this platform for open_datasync and open_sync. Compare file sync methods using one 8kB write: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 75.111 ops/sec fdatasync 71.925 ops/sec fsync 37.352 ops/sec fsync_writethrough n/a open_sync 33.746 ops/sec Compare file sync methods using two 8kB writes: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 38.204 ops/sec fdatasync 49.907 ops/sec fsync 32.126 ops/sec fsync_writethrough n/a open_sync 13.642 ops/sec Compare open_sync with different write sizes: (This is designed to compare the cost of writing 16kB in different write open_sync sizes.) 1 * 16kB open_sync write 25.325 ops/sec 2 * 8kB open_sync writes 12.539 ops/sec 4 * 4kB open_sync writes 6.207 ops/sec 8 * 2kB open_sync writes 3.098 ops/sec 16 * 1kB open_sync writes 1.208 ops/sec Test if fsync on non-write file descriptor is honored: (If the times are similar, fsync() can sync data written on a different descriptor.) write, fsync, close 27.275 ops/sec write, close, fsync 20.561 ops/sec Non-Sync'ed 8kB writes: write 562902.020 ops/sec 

在arrays和单个磁盘上运行testing几次之后,数字看起来变化很大。 最差的情况下,性能约为我在这里发布的50%(第一次testing的时候约为30 ops / s)。这是正常的吗? 机器一直处于空闲状态。

另外,根据dmesg输出,控制器处于AHCI模式。

服务器有令人难以置信的,难以言喻的,非常慢的fsync性能。 您的软件RAID 1设置有一些非常严重的错误。 可怕的fsync性能几乎肯定是性能问题的原因。

桌面只是非常缓慢的fsync

您可以通过设置synchronous_commit = off并设置commit_delay来解决性能问题,其代价是在崩溃后丢失一些数据。 你真的需要在服务器上理清磁盘的性能,但是,这是令人沮丧的。

为了比较,这是我的笔记本电脑(i7,8GB内存,中档128G SSD,从9.2的pg_test_fsync):

 Compare file sync methods using one 8kB write: open_datasync 4445.744 ops/sec fdatasync 4225.793 ops/sec fsync 2742.679 ops/sec fsync_writethrough n/a open_sync 2907.265 ops/sec 

不可否认的是,这款SSD可能并不是硬盘电源的安全保护,但是当我们谈论服务器成本的时候,它并不像是一个体面的电源,故障安全的SSD成本很高。

这是我服务器上的pg_test_fsync输出,configuration非常相似 – 两个消费级磁盘( WD10EZEX-00RKKA0 )上的Linux软件RAID1:

 # ./pg_test_fsync -s 3 Compare file sync methods using one 8kB write: (in wal_sync_method preference order, except fdatasync is Linux's default) open_datasync 115.375 ops/sec fdatasync 109.369 ops/sec fsync 27.081 ops/sec fsync_writethrough n/a open_sync 112.042 ops/sec ... 

你在完全空闲的服务器上testing过,是吗?


也许你有没有alignment的分区。 检查:

 parted /dev/sda unit s print 

这是我的服务器的输出:

 Model: ATA WDC WD10EZEX-00R (scsi) Disk /dev/sda: 1953525168s Sector size (logical/physical): 512B/4096B Partition Table: msdos Number Start End Size Type File system Flags 1 2048s 67110911s 67108864s primary ext4 boot, raid 2 67110912s 603981823s 536870912s primary raid 3 603981824s 608176127s 4194304s primary linux-swap(v1) 4 608176128s 1953523711s 1345347584s primary raid 

检查“ Start列中的每个数字是否可以被2048整除(表示1MiB)。 对于可以被4除尽的好的4096Balignment就足够了,但alignment感知实用程序在1MiB边界处开始分区。


另外也许你正在使用非默认的挂载选项,如data=journal ,这对性能有很大的影响。 显示你的: mount -v | grep ^/dev/ mount -v | grep ^/dev/ 。 这是我的:

 /dev/md0 on / type ext4 (rw,barrier,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0) /dev/md2 on /home type ext4 (rw,barrier,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0) /dev/md1 on /var type ext4 (rw,barrier,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0) 

也许你的一个磁盘坏了。 在没有RAID的每个磁盘上创build一个分区(也许你在这两个磁盘上保留了一些交换分区 – 使用这些 – 无论如何都不用交换RAID)。 在那里创build文件系统,并在每个驱动器上运行pg_test_fsync – 如果有问题,那么当两者都镜像时,好的一个就不得不等待它。


检查您的BIOS设置为使用AHCI模式而不是IDE模式。 一个服务器将受益于本地命令队列 ,这在IDE模式下是不可用的。


忽略与SSD的比较。 比较是荒谬的。

我知道我可能来不及回答这个问题。 在使用O_DIRECT时,我发现PostgreSQL和MySQL有类似的性能问题。 我使用iozone和同步写入( – + r选项)以及使用和不使用O_DIRECT(-I选项)对微系统进行了基准testing。 以下是我使用的两个命令:

 iozone -s 2g -r 512k -+r -I -f /mnt/local/iozone_test_file -i 0 

 iozone -s 2g -r 512k -+r -f /mnt/local/iozone_test_file -i 0 

第一个是O_SYNC + O_DIRECT,而第二个只是O_SYNC。 第一次我得到大约30MB /秒,第二次我得到约220MB /秒(SSD驱动器)。 我发现,ext4接缝上的has_journal选项会导致问题。 不知道为什么…

 Filesystem features: has_journal 

一旦我拿出这个选项,事情开始正常工作,两个testing达到和维持220MB /秒。 要取出选项,可以使用如下所示的内容:

 tune2fs -O ^has_journal /dev/sdX 

你可以给一个testing,看看它是否解决了你的性能问题。