天天看点

一个笛卡尔积的update from引发的问题(内存泄露?)

postgresql支持多表join的更新操作,但是如果sql没有写好,可能会导致出现笛卡尔积的情况。

如果是条查询语句,出现笛卡尔积时,没什么问题,大不了就是查询慢一点。

如果是条更新语句,现在看来可能代码中有内存泄露的bug,已反馈给pg社区。

另外需要注意postgresql不允许自关联的更新,但实际上使用别名可以规避这个语法错误

如果业务确实有自关联的更新操作需求,可以使用别名的方法。

使用别名规避以上错误

另外需要注意,以上query已经产生了笛卡尔积,三个表(tbl1, tbl1, tbl2)的join,但是只提供了一个join条件。

虽然以上是一条问题sql,但是接下来的问题也是这样的问题sql发现的。

执行以下query生成测试数据

执行以下sql即可复现问题。

sql的执行计划如下

这里join会用到临时空间,所以如果在这一步使用temp_file_limit限制了临时文件的使用,可能会报错。

复现问题时,可以把它设到无限大(-1),其实本例设成1gb就够用了,因为造成问题的不是temp file.

这样会无休止执行下去,同时导致内存不断增长,这个内存占用和temp file没有关联,应该是某处内存泄露导致的。

pmap可以看到该进程一处anonymous内存不断的膨胀

使用bt打印该进程的调用栈

使用oprofile分析当时数据库的问题

下载并安装最新oprofile

<a href="http://oprofile.sourceforge.net/news/">http://oprofile.sourceforge.net/news/</a>

采集信息

等待120秒后ctrl+c 退出

生成报告

查看对应的函数调用

查看对应的函数调用, 哪些语句花了更多的cpu

这个update对应的查询不会导致内存膨胀

同样采集系统信息进行分析

查看报告

update时跟踪到了allocsetalloc,但是比allocsetfree多很多。

select时同时跟踪到了allocsetalloc,allocsetfree,都不太多,虽然两者的比例差不多。

update时会不会是这里有内存泄露呢?

进一步分析

分配分析

回收分析

1. 写sql时需要注意,避免产生笛卡尔积。

2. 这个问题已反馈给社区,看看是不是存在内存泄露。

tom lane的速度太快了,从报bug到现在10个小时过去,已经修复 。

<a href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=blobdiff;f=src/backend/access/heap/heapam.c;h=6a27ef4140091b0c53d3a68f9d947824b2ffe8c2;hp=c63dfa0bafc606ea3dc1ee9c7427d92c28ed09d4;hb=ae4760d667c71924932ab32e14996b5be1831fc6;hpb=ca9cb940d23dc8869a635fa27a08e60837b17c07">https://git.postgresql.org/gitweb/?p=postgresql.git;a=blobdiff;f=src/backend/access/heap/heapam.c;h=6a27ef4140091b0c53d3a68f9d947824b2ffe8c2;hp=c63dfa0bafc606ea3dc1ee9c7427d92c28ed09d4;hb=ae4760d667c71924932ab32e14996b5be1831fc6;hpb=ca9cb940d23dc8869a635fa27a08e60837b17c07</a>