我最近收到“共享内存不足 - 您可能需要增加 max_locks_per_transaction”错误。
这是一个长时间运行的过程,我在正确处理后导入一堆 CSV 文件。我遍历它们并为每个文件打开一个事务,处理它,然后当我完成文件时,关闭事务并移至下一个文件。
这些文件并不大,最大的大约 12K 行。
就 PG 而言,我所做的处理相当于做几个SELECT
s(每行几个,没有连接或任何东西),然后是UPDATE
一个现有行(每行最多一个)。
问题是,pg_locks
填充了没有relation
、类型transactionid
和模式为 的事务ExclusiveLock
。我有多达 20K 行这样的行pg_locks
,除了那些,正如预期的那样,参考我正在使用的两个表,绝大多数看起来像这样(对不起,缩进会被搞砸,我正在发布一个指向 pastebin 的链接):
"locktype" "database" "relation" "page" "tuple" "virtualxid" "transactionid" "classid" "objid" "objsubid" "virtualtransaction" "pid" "mode" "granted" "fastpath"
"virtualxid" "" "" "" "" "11/18291" "" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "t"
"transactionid" "" "" "" "" "" "61840165" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
"transactionid" "" "" "" "" "" "61843843" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
"transactionid" "" "" "" "" "" "61833173" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
"transactionid" "" "" "" "" "" "61835511" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
"transactionid" "" "" "" "" "" "61846000" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
"transactionid" "" "" "" "" "" "61838308" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
"transactionid" "" "" "" "" "" "61832936" "" "" "" "11/18291" "6308" "ExclusiveLock" "t" "f"
基本上,这些记录都没有数据库或关系,只有事务 ID。
唯一不同的行是第一行,我认为它来自获取自身锁定的事务。
所有的锁都是由同一个连接获取的,显然只有在执行时才可以UPDATE
,这实际上并不比
UPDATE t SET foo = COALESCE(foo, 0) + 23.4 WHERE bar = 'hey' and baz = 'ho'
并且最多可以影响一行。
当我处理完文件并提交事务时,所有这数千条记录都会从 中消失pg_locks
,回到更正常的 15 到 30 条之间。就好像每条记录都UPDATE
以某种方式获得了一个锁,使记录计数pg_locks
增加每隔一两秒调一个。
我想我一定做错了什么,但我不知道是什么。
作为一种临时解决方法,我确实增加了 max_locks_per_transaction,但我真的很想真正解决这个问题。我认为我的用例不需要增加 max_locks_per_transaction,这很简单。
另外,请注意没有其他人正在访问我正在使用的两个表。甚至没有人访问同一模式中的任何表。
我在 Windows Web Server 2008 R2 上。
PostgreSQL 9.3.5,由 Visual C++ build 1600 编译,64 位
与 Npgsql 2.2.5 连接
任何人都可以解释一下吗?
我考虑过可能的索引问题,但是有问题的表无论如何都不大(少于 50K 行),并且SELECT
使用与使用的相同标准对其进行UPDATE
操作非常快。
提前致谢。