将被终止。通过适当增加 max_locks_per_transaction 参数的值我们可以避免由于锁限制导致的错误或性能下降。pg_dump: 最后的内置 OID 是 16383 pg_dump: 读扩展 pg_dump: 识别扩展成员 pg_dump: 读取模式 pg_dump: 读取用户定义表 pg_dump: 错误: 查询失败: 提示: You might need to increase max_locks_per_transaction. pg_dump: detail: Query was: LOCK TABLE public.t_1411568720613943894, public.t__776845678375982004, public.t_1318598144, public.t__1084185515, public.t__941540929, public.t__240429387, public.t_1487200566, public.t_990720474, public.t__673777124, public.t__3842978921671954791, public.t__18356806761671954791, public.t__2110790801990202598, public.t__393453906990202598, public.t__1317384021990202598, public.t__727135582990202598, public.t__635583730990202598, public.t_1317302062990202598, public.t__66599909843609561, public.t_195843915143609561, public.t__127787303443609561, public.t_110181100843609561, public.t__210390485943609561, public.t__181974289643609561, public.t_173020648043609561, public.t__159803795743609561, public.t__108891614743609561, public.t__20830166243609561, public.t__118260254643609561, public.t_11034225943609561, public.t_128241074643609561, public.t__60683613543609561, public.t__46536326843609561, public.t_198912020943609561, public.t__629890994375982004, public.t__104504776375982004, public.t__186422411943609561, public.t__11641007043609561, public.t_87765719243609561,问题原因在使用postgres执行一个存储过程存储过程的操作是对全库上百张表添加字段执行到一半的时候抛出了错误You might need to increase max_locks_per_transaction。抛出的异常信息可以看出是因为公共内存溢出导致的这个问题在Postgres官方找到了解释most likely possibility you have a transaction being left open and accumulating locks. of course, you have to rule out the fact that you simply have to increase max_locks_per_transaction: if you have a lot of tables, it might be reasonable to have to extend this on a stock config. one thing that can cause this unfortunately is advisory locks eating up exactly the amount of shared memory you have. thats another thing to rule out. 大意是开启事务后每次操作一张表会进行一次表级的lock操作并增加lock的大小当lock的大小超过了默认的限定值就会抛出异常。 共享锁表跟踪在max_locks_per_transaction * (max_connections max_prepared_transactions) 个对象如表上的锁。 因此在任何一个时刻只有不超过这么多个可区分对象能够被锁住。这个参数控制为每个事务分配的对象锁的平均数量。 个体事务可以锁住更多对象数量可以和锁表中能容纳的所有事务的锁一样多。这不是能被锁住的行数那个值是没有限制的。 默认值 64 已经被历史证明是足够的但是如果你有需要在一个事务中使用很多不同表的查询例如查询一个有很多子表的父表你可能需要提高这个值。这个参数只能在服务器启动时设置。 当运行一个后备服务器时你必须设置这个参数为大于等于主服务器上的值。否则后备服务器上将不允许查询。问题原因已经找到是因为一个过程中操作的表过多超过了最大对象锁的限制数量导致了异常。解决办法可以先看看 数据库的配置-- postgres中默认max_locks_per_transaction大小是64 show max_locks_per_transaction; 结果 max_locks_per_transaction --------------------------- 64 (1 row)解决方案一修改数据库配置第一步修改 PostgreSQL 配置文件 (postgresql.conf)你需要手动编辑 PostgreSQL 的主配置文件增加它的“锁容量”。找到文件路径根据你的脚本PostgreSQL 安装在 E:\ 盘。请打开文件夹E:\Program Files\PostgreSQL\17\data\找到文件postgresql.conf编辑文件右键点击该文件选择“打开方式” - “记事本”或者用 VS Code、Notepad。搜索文件按 Ctrl F 搜索关键词max_locks_per_transaction。你会看到这一行通常在文件中间偏下的位置#max_locks_per_transaction 64修改操作去掉行首的井号 #取消注释。将数值 64 改为 512为了保险直接给足空间这里看情况改为128 或者 512根据实际情况。修改后的样子应该是max_locks_per_transaction 512保存文件点击“文件” - “保存”。如果提示“拒绝访问”说明你没有管理员权限。请右键点击记事本图标选择“以管理员身份运行”然后再通过记事本打开并修改该文件。第二步重启 PostgreSQL 服务修改配置文件后必须重启数据库服务才能生效。按下键盘上的 Win R 键。输入 services.msc 并回车。在服务列表中找到名为 postgresql-x64-17 (或者名称中包含 PostgreSQL 17 的那一项)。右键点击它选择 “重新启动”。第三步运行原脚本服务重启成功后。不要修改你的备份脚本直接运行你最原始的脚本就是没有加 -L 或 --no-locking 参数的那个版本。此时数据库已经拥有了足够的内存来处理这几百张表的锁请求备份将正常进行不再报错。解决方案二修改备份脚本如果你无法重启数据库服务可以通过修改pg_dump的参数让它不要一次性锁定所有表。添加参数--no-locking 或者 --lock-wait-timeout10s修改你的脚本第3步备份命令将原来的这行%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%修改为增加了--lock-wait-timeout1s或者直接去掉锁注意最简单的绕过方法是使用--no-locking但这在备份期间如果有 DDL建表/删表操作可能会导致备份不一致。鉴于你的表名看起来像系统生成的临时表通常可以使用此参数。%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v --no-locking -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%或者如果你希望它等待而不是报错可以加超时%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v --lock-wait-timeout10s -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%使用改方案可能还有报错需要进一步处理看下方解决办法解决办法使用短参数报错信息E:\Program Files\PostgreSQL\17\bin\pg_dump.exe: illegal option -- no-locking pg_dump: hint: Try pg_dump --help for more information.报错原因pg_dump.exe: illegal option -- no-locking这说明你的 PostgreSQL 版本即使是 17 版本可能对参数的解析方式比较严格或者该版本编译时不支持直接使用长参数形式。修正操作PostgreSQL 的pg_dump通常支持短参数-L来表示不加锁。请将你的脚本中执行备份的那一行修改为修改前%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%修改后增加了-n参数%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v -n -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%或者如果-n不行尝试-L%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v -L -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%参数解释-L或--lock-wait-timeout的短形式有时能绕过长参数的解析错误或者直接使用--lock-wait-timeout1强制报错而不是挂起。推荐直接使用这个命令强制锁超时避免死锁也避免参数错误%PGPATH% -h %DB_HOST% -p %DB_PORT% -U %DB_USER% -F c -b -v --lock-wait-timeout1 -f %BACKUP_DIR%%BACKUP_FILE% %DB_NAME%风险悉知修改max_locks_per_transaction这个参数风险非常小通常被认为是安全的“常规运维操作”。你可以放心修改但为了让你心里有底我详细解释一下它具体会有什么影响1. 唯一的“副作用”内存占用微增原理这个参数决定了 PostgreSQL 在启动时要在内存里预留多大一块地盘来存放“锁”的信息。实际影响把数值从64改到512扩大 8 倍听起来很多但实际上占用的内存非常少。通常来说这个改动只会导致数据库多消耗几 MB 到 几十 MB的内存。结论对于现在的服务器通常都是几 GB 甚至几十 GB 内存来说这点内存消耗几乎可以忽略不计完全不会影响数据库性能。2. 生效条件必须重启影响这个参数属于“静态参数”修改后不会立即生效。操作你必须在修改配置文件后重启 PostgreSQL 服务。风险点重启会导致数据库连接短暂中断。建议请在业务低峰期比如凌晨备份时进行重启操作避免影响正在使用系统的员工。3. 极端情况设置过大通常不会发生