为什么PostgreSQL说FATAL:对不起,已经有太多的客户了,而我还没有接近最大连接数?

1 人关注

我正在处理一个安装了PostgreSQL 11.2的系统,它定期在其系统日志中抱怨

FATAL:  sorry, too many clients already

despite being no-where close to its configured limit of connections. This query:

SELECT current_setting('max_connections') AS max,
       COUNT(*) AS total
FROM pg_stat_activity

告诉我,数据库被配置为最多100个连接。 我从来没有见过超过45个连接到数据库的这种查询,甚至在运行的程序收到数据库错误的时刻,说有太多的客户支持,在Postgres日志中的上述信息。

我在互联网上能找到的关于这个问题的绝对一切都表明,这个错误意味着你已经超过了max_connections的设置,但数据库本身告诉我,我没有。

值得一提的是,pyspark是唯一一个触发这个错误的数据库客户端,而且只在它从数据帧写入表的时候。 使用psycopg2的普通python代码(也就是主要的客户端)从未触发过这个错误(甚至在以同样的方式从Pandas数据帧写入表时也没有),像pgAdmin这样的管理工具也从未触发过。 如果我没有在数据库日志中直接看到这个错误,我会认为Spark在错误上对我撒谎。 大多数情况下,如果我使用这样的查询。

SELECT pg_terminate_backend(pid) FROM pg_stat_activity 
WHERE pid <> pg_backend_pid() AND application_name LIKE 'pgAdmin%';

然后这个问题就会消失好几天。 但就像我说的,根据数据库本身,我从来没有见过所谓的最大100个连接中的50%在使用。 我怎样才能找出导致这个错误的原因?

5 个评论
你是否尝试过设置 log_connections log_disconnections 参数来捕获postgresql服务器日志文件中的连接? 你可以把这些信息拉出来分析一下,看看这些连接是从哪里来的,这可能会突出问题所在。
你可以在几分之一秒内从45个连接变成101个连接。 你从来没有看到它的进展,并没有提供多少证据。
@blackbishop 我目前在从 pyspark 写入时没有使用 numPartitions 。 我是用 df.write.jdbc(...) 写到数据库的。 替换代码0】的值是否应该与火花配置中的 spark.cores.max 设置有任何联系?
@smbennett1974 - 好主意,我会在下次出现这种情况时记录连接和断开的情况。 连接到这个数据库的普通应用程序使用连接池,所以总共不会超过30个连接。 然而,Spark会建立自己的连接。 Spark有可能在一秒钟内从一个 df.write.jdbc(...) 的调用中向数据库建立几十个连接吗?
@Eddie 你可以尝试设置 numPartitions 小于100。 sql-data-sources-jdbc : " 这也决定了并发的JDBC连接的最大数量 ".
python
postgresql
apache-spark
pyspark
spark-jdbc
Eddie
Eddie
发布于 2021-02-13
2 个回答
blackbishop
blackbishop
发布于 2021-02-14
已采纳
0 人赞同

这是由Spark使用JDBC读/写数据的方式引起的。Spark试图打开几个并发的数据库连接,以便并行地读/写多个分区的数据。

我在文档中找不到,但我认为默认情况下,连接数等于你想写进db表中的数据名的分区数。这就解释了你所注意到的间歇性问题。

然而,你可以通过设置以下内容来控制这个数字 numPartitions option:

在表的读写过程中,可用于并行的分区的最大数量。 表的读和写。这也决定了最大数量的 并发的JDBC连接数。如果要写入的分区数量 超过这个限制,我们通过调用 coalesce(numPartitions) 后再写入。

spark.read.format("jdbc") \
          .option("numPartitions", "20") \
# ...
    
Laurenz Albe
Laurenz Albe
发布于 2021-02-14
0 人赞同

Three possibilities:

  • 这些连接是非常短暂的,当你看的时候,它们已经消失了。

  • 你在该数据库上有一个较低的连接限制。

  •