首页 > 解决方案 > 为什么 INSERT 查询无限期挂起并锁定 PostgreSQL 数据库和 pgAdmin

问题描述

我有一个 Spring Batch 应用程序(尽管我认为我已经消除了 Spring 作为罪魁祸首——更多内容见下文),它使用驱动程序的42.2.8版本org.postgresql连接到作为 AWS RDS 实例提供的 PostgreSQL 11.1 数据库。该应用程序正在从 Oracle 设置迁移,但每当我尝试运行应用程序来摄取数据时,它会无限期地锁定进程,并且在某种程度上似乎锁定了数据库本身......

出于某种原因,当转换为以 postgres 为目标时,可以很好地摄取到 Oracle 中的代码似乎完全阻塞了 INSERT 语句(无论是 Spring 生成它们,还是我尝试通过放置 INSERT 语句来绕过对 Spring 的所有调用和连接信息硬编码到应用程序主函数的顶部)。

最重要的是,在我终止挂起的进程之前,我什至无法在 pgAdmin 中做某​​些事情。Web 界面也无限期挂起,我正试图找出它的韵律或原因(我不能怪表,因为其他表可能会被阻塞,有时可以访问;有时我可以建立新的连接,有时我不能;只要我不杀死选项卡/连接,我似乎确实能够可靠地刷新我以前查询过的表)

我不确定 Spring 是否在简单调用周围自动装配或自动注入某些东西,所以我将制作一个简单的 Java 应用程序来尝试消除这种可能性......我也可以尝试不同的 postgres 驱动程序,但令我担心的是,它似乎挂起了 pgAdmin 网络界面......但无论如何,我希望有人遇到过并修复或缓解这种情况,而且它还没有最终出现在一篇易于谷歌搜索的文章中

有人有这个问题吗?有或没有 Spring Batch?

标签: javaspringpostgresqljdbc

解决方案


首先,我在 pgAdmin Dashboard 上找到了 Sessions 选项卡,它指向另一个被标记为阻止新会话的会话——一个从 python 脚本调用的截断函数,它完成并返回控制(所有数据都从表) - 所以它仍然阻止任何东西并不明显

我发现这个锁定/阻塞关系的表/矩阵确实清楚地表明截断会阻塞一切:

表锁在 DDL 期间阻止读取和/或写入

无论如何......我意识到python脚本试图重用步骤1中的数据库连接(通过psycopg2从python直接调用Oracle中的存储过程,或PostgreSQL中的函数),然后保持db连接(所有步骤都是在单个 with 语句块的范围内),因为它为步骤 2 启动了一个 java 进程(它将写入在步骤 1 中被截断的表)。python 进程将等到 java 进程终止,然后将相同的 db 连接传递给在步骤 3 中直接从 python 调用的存储过程。

对这种方法的批评是肯定的,Oracle 似乎处理得很好,但 Postgres 不同意,锁定在第 2 步,因为我只能从我的阅读和我能找到的少数记录中假设,截断实际上并没有提交或其他什么(? )

我的解决方法似乎来自于在第 1 步完成之后,在开始 Java 进程之前关闭 python 中的连接。然后我获得了第 3 步的另一个连接,现在看来一切正常


推荐阅读