总 结
PostgreSQL 通过调用系统 fsync() 或者其他使得事务内容写入到物理磁盘,这样可以保证操作系统或者数据库出现宕机后,仍然可以恢复到某一个一致性的状态。理论上讲 PostgreSQL 的 fsync 功能关闭,可以实现性能的提升,但是带来的影响就是需要承担数据的丢失,因为出现系统宕机或者数据库崩溃的时候有一些数据是没有落盘的。
本文将验证 fsync 参数的性能影响,以及参数关闭时数据库宕机后的影响。
数据量:1000W
fsync 参数:on
初始化表:user_info
pgbench 压测
pgbench 结果
pgbench 压测
pgbench 结果
数据量:1000W
fsync 参数:off
初始化表:user_info
pgbench 压测
pgbench 结果
pgbench 压测
pgbench 结果
通过对比发现,将 fsync 改为 off,对于读 TPS,参数 fsync 的影响不大,对于写 TPS,性能有一定提升。
现在验证参数关闭时数据库宕机后的影响
首先,使用将数据库性能跑起来
然后,模拟服务器断电
之后,启动数据库
提示信息:比致命错误还过分的错误。
结果:数据库无法启动,原因就是因为无法找到一个有效的 checkpoint 记录,这就是因为 fsync 设置为 off,由于数据库异常宕机导致。可以通过使用 pg_resetxlog 恢复数据库,但是会造成部分数据无法找回,数据丢失;也可以通过备份恢复,同样也会丢失部分数据。
fsync 参数对于读 TPS 的性能影响不大,对于写 TPS 的性能有一些影响,设置为 off,写 TPS 性能有一定提升,但是存在数据库宕机后无法正常启动,即使恢复后启动数据库,也会有数据丢失的很大风险。因此生产环境非必要时,不要将此参数设置为 off,还是使用默认的 on 比较稳妥。
C库提供了fwrite接口,在调用write之前将数据缓存到buffer,buffer大小可以通过setvbuf来设置。
int setvbuf(FILE *stream, char *buffer, int mode, size_t size)
参数
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流。
buffer -- 这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲。
mode -- 这指定了文件缓冲的模式:
模式描述
_IOFBF 全缓冲 :对于输出,数据在缓冲填满时被一次性写入。对于输入,缓冲会在请求输入且缓冲为空时被填充。
_IOLBF 行缓冲 :对于输出,数据在遇到换行符或者在缓冲填满时被写入,具体视情况而定。对于输入,缓冲会在请求输入且缓冲为空时被填充,直到遇到下一个换行符。
_IONBF 无缓冲 :不使用缓冲。每个 I/O 操作都被即时写入。buffer 和 size 参数被忽略。
当fwrite数据超过buffer大小,就会自动刷新到内核缓存,如果希望立刻刷新,就可以调用fflush。
此时内核缓存的数据并没有立刻同步到磁盘中去,会等待一个IO同步周期,然后同步到磁盘中去,比如在android设备中,同步周期为5秒钟左右,如果开发音视频录制功能,在同步周期到来之前发生掉电或程序Crash,则会发生数据丢失的问题,即使APP已经调用了fwrite。
如果希望内核缓存立刻同步到磁盘,可以调用fsync来强制系统执行IO同步,这个方法是阻塞方法,需要等待IO同步到磁盘完成后才会返回,所以需要注意调用的线程是否可以执行耗时的操作。
关系如下:
app --------fwrite------> c库缓冲-----fflush--------->内核缓冲--------fsync----->磁盘
sync(意指Synchronize,即“同步”)为UNIX操作系统的标准系统调用,功能为将内核文件系统缓冲区的所有数据。
sync作为C语言的函数之一,sync()一般以void sync(void)的形式在unistd.h内声明。该函数也可以从命令行执行sync命令的方式调用,同时在其他程序语言(如Perl)中也有名字与之相似的函数。
UNIX中还有一些与sync相似的系统调用,如fsync与fdatasync。其中fsync负责写入所有与特定文件描述符相关的缓冲区数据;fdatasync功能与fsync相似,但只负责写入文件中被变更的数据,而不会修改文件的元数据(如文件属性)。
sync在数据库中的应用
在对数据进行修改操作(包括增、删、改)时,被修改的数据一般仅是暂存于基于内存的写入缓存,而当掉电时这些修改便会丢失;而为保证数据的持久性,数据库必须使用某些形式的sync,以确保修改的内容切实写入非易失性存储器,如PostgreSQL就使用了多种sync类调用(包括fsync与fdatasync)来达到这一目的。
但是,对于旋转寻道的硬盘来说,每次旋转只能完成一项“提交”操作以将客户端的修改写入,因此每秒最多只能完成几百次的“提交”操作;而若关闭fsync的限定来放宽要求,则可大幅提升性能,但同时也会带来系统崩溃后数据库损毁的潜在危险。有鉴于此,数据库也使用囊括最近修改信息的日志文件(一般比主题数据文件小得多)来保障可靠性:根据日志文件,系统管理员可以在系统崩溃后准确地重做修改操作,以此即可减少对主要数据文件的sync操作。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)