APP下载

GitLab发现子交易语法可能使PostgreSQL数据库出现停顿

消息来源:baojiabao.com 作者: 发布时间:2024-10-02

报价宝综合消息GitLab发现子交易语法可能使PostgreSQL数据库出现停顿

GitLab在去年6月的时候,发现GitLab.com出现不寻常的停顿,经过调查才知道,在数据库PostgreSQL中,透过SAVEPOINT SQL查询起始子交易,则正在进行中的长交易(Long Transaction),有可能会对数据库的副本产生严重效能冲击。

只所以会发现这个问题,是GitLab观察到CI/CD Runner服务偶而会出现高错误率,用来检索CI/CD建置资料的数据库查询发生超时的状况,并且未处理的建置积压迅速成长。

而这个问题难以调查的程度,官方将其称之为Nessie,意思是这个问题就像是尼斯湖水怪一样,无法预测出现的时机。官方提到,数据库查询停滞的情况随机出现,而且停顿可能持续15分钟后就消失,几天后才会再出现。

数据库停顿伴随一些模式,GitLab发现只有数据库副本会受到影响,主要数据库运作正常,在发生停顿期间,通常有一个长时间执行的交易正在进行,通常和PostgreSQL自动清理有关,只要长交易结束,停顿也会迅速停止。经过了长时间的调查,以及诸多假设与验证,GitLab终于发现并且能够重现这个问题。

官方称这个问题为Subtrans SLRU溢位,肇因是忙碌的数据库,可能使子交易日志的大小,庞大到工作集无法存在内存中,这将导致大量快取未命中,进而造成大量磁盘I/O和CPU负载,因为PostgreSQL会疯狂地尝试从磁盘中载入资料,以符合查询使用。官方提到,只要在长交易间,有一个SAVEPOINT出现,就会造成这个问题。

在PostgreSQL中,交易从 BEGIN语句启动,而SAVEPOINT则是开始子交易,官方举例解释需要使用SAVEPOINT的理由,当消费者在线上商店下订单,意外地同时有两笔订单抵达数据库,要让数据库不因为重复建立账户,导致其中一笔订单失败,而是希望可以在订单直接使用该账户,开发者便能以SAVEPOINT来进行子交易,先进行查询,使用刚刚建立的账户并且完成订单。

要解决Nessie数据库停顿问题有三个选择,完全消除SAVEPOINT的呼叫、消除所有长时间执行的交易,或是在PostgreSQL加入应急修补程式。GitLab先选择方案一,消除SAVEPOINT的呼叫来解决这个问题。官方提到,消除数据库的长交易不切实际,而且许多长交易是数据库的自动清理,要从这方面下手,需要花费过多的时间精力。

而官方同时也在考虑对PostgreSQL安装修补程式,但是安装修补程式有许多需要考量的点。修补程式虽然能够借由增加快取到100 MB,来解决SAVEPOINT的问题,但是快取达100 MB,会让搜寻成本变高。

问题不只如此,当使用了应急修补程式,便会使得GitLab所使用的PostgreSQL成为非官方版本,这会大幅增加基础设施团队的维护成本,而且自我托管的用户也必须安装修复程式,才能解决问题。

官方目前选择成本最低的方案,消除SAVEPOINT的呼叫,来避免Nessie问题,而GitLab在删除SAVEPOINT之后,也就没有再遭遇到数据库停顿的状况,GitLab提到,他们建议所有PostgreSQL的使用者,要执行只读副本的PostgreSQL,也应该删除所有子交易,避免遇到Nessie问题。

2021-10-05 10:52:00

相关文章