postgresql 错误:由于用户请求而取消语句

Posted

技术标签:

【中文标题】postgresql 错误:由于用户请求而取消语句【英文标题】:postgresql error: canceling statement due to user request 【发布时间】:2012-10-18 07:45:23 【问题描述】:

postgresql 中出现此错误的原因是什么?

org.postgresql.util.PSQLException: ERROR: canceling statement due to user request

我的软件版本:

PostgreSQL 9.1.6 on x86_64-redhat-linux-gnu, compiled by gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2), 64-bit".

我的 postgresql 驱动是:postgresql-9.2-1000.jdbc4.jar

使用java版本:Java 1.7

提示:我的 postgresql 数据库位于固态硬盘上,此错误是随机发生的,有时根本不会发生。

【问题讨论】:

在 PostgreSQL 9.2.1 上遇到同样的问题(PostgreSQL 9.2.1 on x86_64-unknown-linux-gnu,由 gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-52) 编译), 64 位),具有相同的 JDK 和 postgresql-9.2-1001.jdbc4.jar 驱动程序。数据库在旋转驱动器上,语句取消随机发生,应用程序不取消任何 SQL 语句,语句超时设置为 0(无限期)。尚未确定原因/解决方案。 仅供参考:postgresql-42.2.2 JDBC 驱动程序仍然是实际的 我可能在 postgresql-42.2.9 JDBC 驱动程序上遇到过这个问题(但不确定,可能是其他问题)。我的很奇怪,当我删除了一个按日期字段过滤的 where 和子句时,它就消失了。 更新到 postgresql-42.2.18 JDBC 驱动程序修复了这个问题,我在 AWS EMR 5.29 上使用 spark 2.4.4 scala 2.11 作业得到它。 【参考方案1】:

如果您在不使用事务的情况下收到此错误

用户已请求取消该语句。该声明正在做它被告知要做的事情。问题是,谁要求取消这个声明?

查看代码中准备执行 SQL 的每一行。你可以有一些方法适用于在某些情况下取消该语句的语句,如下所示:

statement = conn.createStatement();
conn.setAutoCommit(true);
statement.setQueryTimeout(25);
my_insert_statement.setString(1, "moobars");

my_insert_statement.executeUpdate();
statement.close();

在我的情况下,发生的事情是我将查询超时设置为 25 秒,而插入时间比这更长。它通过了“由于用户请求而取消声明”异常。

如果您在使用事务时遇到此错误:

如果您收到此异常,请仔细检查执行 SQL 事务的所有代码。

如果您有一个事务中的查询并且您忘记提交,然后您使用该连接执行其他操作,就像您不在事务中一样,则可能存在未定义的行为会产生此异常.

确保执行事务的所有代码都在自行清理。确保事务开始,工作完成,完成更多工作,事务回滚或提交,然后确保连接保持在autocommit=true 状态。

如果这是您的问题,那么在您自己忘记清理的地方不会抛出异常,它会在您未能在事务后清理很久之后发生,这使得它成为难以追踪的异常。刷新连接(关闭它并获取一个新连接)将清除它。

【讨论】:

【参考方案2】:

除了 Eric 的建议之外,您还可以看到语句在以下情况下取消:

以同一用户身份登录的管理员或其他连接使用pg_cancel_backend 要求您的会话取消其当前语句 管理员向运行您的语句的 PostgreSQL 后端发送信号 管理员请求 fast 关闭或重新启动 PostgreSQL 服务器

检查可能取消长时间运行的查询的 cron 作业或负载管理工具。

【讨论】:

【参考方案3】:

这假设 postgresql 的 jdbc jar 文件中的竞争条件错误是造成上述错误的原因。

解决方法 1,定期刷新与数据库的连接

一种解决方法是关闭与数据库的连接并定期创建与数据库的新连接。在每几千条 sql 语句之后,只需关闭连接并重新创建它。然后由于某种原因不再抛出此错误。

解决方法 2,打开日志记录

如果您在设置驱动程序时在 JDBC 驱动程序级别打开日志记录,那么在某些情况下竞争条件问题会被抵消:

Class.forName("org.postgresql.Driver");
org.postgresql.Driver.setLogLevel(org.postgresql.Driver.DEBUG);

解决方法 3,捕获异常并重新初始化连接

您也可以尝试捕获特定异常,重新初始化连接并再次尝试查询。

解决方法 4,等到 postgresql jdbc jar 出现错误修复

我认为问题可能与我的 SSD 硬盘驱动器的速度有关。如果您收到此错误,请在此处发布如何始终如一地重现它,开发人员非常有兴趣消除此错误。

【讨论】:

链接给出 404【参考方案4】:

我们已经找出了这个问题的原因。这是由最新的 JDBC 驱动程序 9.2-100x 中的 setQueryTimeout() 的错误实现来解释的。如果您手动打开/关闭连接可能不会发生这种情况,但通常会在连接池到位且 autocommit 设置为 false 时发生。在这种情况下,应该使用非零值调用 setQueryTimeout()(例如,使用 Spring 框架 @Transactional(timeout = xxx) 注解)。

事实证明,无论何时在语句执行期间引发 SQL 异常,取消计时器都没有被取消并保持活动状态(这就是它的实现方式)。由于池化,后面的连接没有关闭,而是返回到池中。 稍后,当取消计时器触发时,它会随机取消当前与创建此计时器的连接关联的查询。目前,这是一个完全不同的查询来解释随机性效应。

建议的解决方法是放弃 setQueryTimeout() 并改用 PostgreSQL 配置 (statement_timeout)。它没有提供相同级别的灵活性,但至少总是有效。

【讨论】:

一个可能相关的问题已在 v. 9.4.1205 中修复,想知道​​它是否相关:github.com/pgjdbc/pgjdbc/issues/412

以上是关于postgresql 错误:由于用户请求而取消语句的主要内容,如果未能解决你的问题,请参考以下文章

出现错误“由于表单未连接而取消表单提交”

查询失败并显示“错误:由于 VMEM 使用率高而取消查询”

pthread中取消线程

用户取消应用请求后,Laravel 5 Socialite Facebook 登录错误处理回调

使用yum命令出错:SyntaxError: invalid syntax 由于用户取消而退出

调试 CORS 错误的方法