很多"COMMIT;" 在PostgreSQL慢速查询日志中

lor*_*zor 7 postgresql ruby-on-rails

我正在尝试为我正在开发的Rails应用程序优化PostgreSQL 9.1数据库.在postgresql.conf中我已经设置好了

log_min_duration_statement = 200
Run Code Online (Sandbox Code Playgroud)

然后我使用PgBadger来分析日志文件.迄今为止占据大部分时间的声明是:

COMMIT;
Run Code Online (Sandbox Code Playgroud)

我得到的信息不多于此,我对这是什么陈述感到很困惑.有谁知道我能做些什么来获得有关COMMIT查询的更多详细信息?所有其他查询显示语句中使用的变量,SELECT,UPDATE等.但不是COMMIT查询.

Cra*_*ger 8

正如@mvp所指出的那样,如果COMMIT速度慢,通常的原因是缓慢fsync()的,因为每个事务提交都必须将数据刷新到磁盘 - 通常使用fsync()调用.但这并不是缓慢提交的唯一可能原因.你可能会:

  • 如前所述,fsync()的速度很慢
  • 有慢速检查点停止I/O.
  • 有一commit_delay组 - 我没有证实延迟提交被记录为长时间运行的语句,但它似乎是合理的

如果fsync()很慢,那么最好的选择是重新构建您的工作,这样您就可以在更少的大型事务中运行它.一个合理的替代方案可以是使用a commit_delay来对提交进行分组; 这将提交组提交以提高整体吞吐量,但实际上会降低单个事务的速度.

更好的是,解决问题的根源.升级到具有电池备份回写高速缓存的RAID控制器,或升级到电源故障安全的高质量SSD.请注意,普通磁盘通常每转不到一个fsync(),或者每分钟5400到15,000之间,具体取决于硬盘驱动器.有大量的事务和大量的提交,这将大大限制您的吞吐量,特别是因为如果他们所做的一切都是微不足道的冲洗,那是最好的情况.相比之下,如果你在RAID控制器或SSD上有一个持久的写缓存,操作系统不需要确保数据实际上在硬盘上,它只需要确保它已经到达持久写缓存 - 这是大大加快,因为这通常只是一些受电源保护的RAM.

fsync()可能不是真正的问题; 它可能是缓慢的检查站.最好的方法是检查日志,看看是否有关于检查点发生频率过高或持续时间过长的投诉.您还可以启用log_checkpoints记录检查点的长度和频率.

如果检查点花费的时间太长,请考虑调整bgwriter完成目标(参见文档).如果它们太频繁,就增加checkpoint_segments.

有关更多信息,请参阅调整PostgreSQL服务器.


mvp*_*mvp 6

COMMIT是完全有效的语句,其目的是提交当前待处理的事务.由于其真正的性质 - 确保数据真正刷新到磁盘,它可能需要花费大部分时间.

如何让您的应用更快地运作?现在,您的代码可能正在使用所谓的自动提交模式 - 也就是说,每个语句都是隐式COMMIT的.如果您明确地将更大的块包装到BEGIN TRANSACTION;... COMMIT;块中,您将使您的应用程序更快地工作并减少提交次数.祝好运!

  • 虽然非常准确,但请记住,在事务中包装确实会改变应用程序的工作,因为一个错误意味着什么都没有保存到磁盘! (3认同)
  • 在启用AutoCommit的情况下运行时,您将不会在日志中看到COMMIT语句.AutoCommit很可能已关闭,并且每个查询都显式包含在事务块中.这将使得更难以准确地诊断哪些查询导致长时间运行的同步而不打开完整日志记录. (2认同)