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>