我有两张桌子:
CREATE TABLE foo (
id serial primary key,
abc text
);
CREATE TABLE bar (
id serial primary key,
xyz text
);
我在表foo
上有一个触发器:
CREATE FUNCTION foo_before_insert()
RETURNS trigger AS
$BODY$
BEGIN
INSERT INTO bar (id, xyz)
VALUES (
NEW.id,
FooFunction(NEW.abc)
);
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
CREATE TRIGGER foo_before_insert
BEFORE INSERT ON foo
EXECUTE PROCEDURE foo_before_insert();
因此,当某些内容插入foo
时,某些内容也会插入bar
,abc
列会被FooFunction
操纵。这是简化版。
真实世界FooFunction
获取经度和纬度的两个数字参数,for loop
SELECT
查询选择单个几何列,是否使用几何列执行一些Postgis函数和输入,并返回一个布尔值。基本上,该函数试图确定一个点是否位于一组多边形中的至少一个多边形内。
这里有功能的肉和土豆:
FOR currentLinestring IN
SELECT linestring
FROM bla
WHERE yadda yadda...
LOOP
currentLinestring = ST_MakeLine(currentLinestring);
-- Can't make polygon with under 4 points
IF ST_NPoints(currentLinestring) < 4 THEN
EXIT;
END IF;
IF ST_Contains(ST_MakePolygon(currentLinestring), ST_SetSRID(ST_MakePoint(_lon, _lat), 4326)) = TRUE THEN
-- Is not out of bounds
RETURN FALSE;
END IF;
END LOOP;
-- Is out of bounds
RETURN TRUE;
捕获是在触发器外部(如质量更新)时功能100%正常但在触发器功能内部时,Postgres的内存使用量会攀升并攀升,直到所有内存耗尽并且Postgres崩溃。当我COPY
使用可能有10万行的大型CSV时,会发生这种情况。
造成这种情况的原因是什么?我该如何解决这个问题?
答案 0 :(得分:0)
第一个重要的问题是,如果事务提交后内存被释放(尝试使用较小的CSV文件)。如果情况并非如此,则会使问题更严重。
接下来要检查的是PostgreSQL服务器日志中的内存转储,看起来有点像这样:
TopMemoryContext: 221952 total in 17 blocks; 7440 free (41 chunks); 214512 used
TopTransactionContext: 8192 total in 1 blocks; 6384 free (0 chunks); 1808 used
CurTransactionContext: 0 total in 0 blocks; 0 free (0 chunks); 0 used
Type information cache: 24240 total in 2 blocks; 3744 free (0 chunks); 20496 used
RI compare cache: 24576 total in 2 blocks; 15984 free (5 chunks); 8592 used
...
查看哪个内存上下文包含所有内存。
您应该确保最近修补了PostgreSQL和PostGIS。
有可能内存在某些PostGIS功能中泄露。 尝试通过消除一些功能尽可能地缩小范围,直到你知道哪一个是罪魁祸首。
然后创建一个简单的测试用例,让人们重现问题并将问题报告给PostGIS(如果你可以在没有PostGIS的情况下重现问题,则报告PostgreSQL),包括你的所有发现(内存环境......)。
如果您无法解决此问题,这是解决此问题的最佳方法,例如将工作分成多个交易。