PostgreSQL:后端进程长期处于活动状态

时间:2018-12-20 13:32:49

标签: postgresql

现在我遇到了很大的障碍。

我使用PostgreSQL 10及其新的表分区。

有时候,当我通过active检查后端进程时,许多查询不会返回,并且许多后端进程是pg_stat_activity。 首先,我认为这些过程只是在等待lock,但是这些事务仅包含SELECT语句,而另一个后端不使用任何需要ACCESS EXCLUSIVE锁定的查询。这些仅包含SELECT语句的查询在计划方面没有问题。通常,这些效果很好。而且计算机资源(CPU,内存,IO,网络)也没有问题。因此,这些翻译绝不应冲突。而且我通过pg_lockspg_blocking_pids()仔细检查了这些事务的锁,最后我找不到任何会使查询变慢的锁。许多处于活动状态的后端仅持有ACCESS SHARE,因为它们仅使用SELECT。 现在,我认为这些现象不是由锁引起的,而是与新表分区有关的。

那么,为什么有许多后端处于活动状态? 有人可以帮我吗? 任何意见,高度赞赏。 打击数字是pg_stat_activity结果的一部分。 如果您需要任何其他信息,请告诉我。

enter image description here

编辑

我的查询无法处理大数据。返回类型是这样的:

uuid UUID
,number BIGINT
,title TEXT
,type1 TEXT
,data_json JSONB
,type2 TEXT
,uuid_array UUID[]
,count BIGINT

因为它具有JSONB列,所以我无法计算确切的值,但是它不是大JSON。 通常,这些查询速度适中(大约1.5秒),因此绝对没有问题,但是当其他进程正常工作时,就会发生这种现象。 如果统计信息错误,查询总是很慢。

EDIT2

这是统计信息。几乎有100个连接,因此我无法显示所有统计信息。

enter image description here

5 个答案:

答案 0 :(得分:3)

对我来说,这看起来像是应用程序问题,而不是postresql的问题。 active状态表示您的交易仍未提交。

那么,为什么您的应用程序可能无法将commit发送到数据库?

尝试查看您何时在应用程序代码中open transactionread datacommit transactionrollback transaction

编辑: 顺便说一句,要确保在问题出现之前以及查询开始挂起之前尝试检查资源使用情况。尝试运行topiotop来检查出现问题时postgres是否真的开始像疯狂地吃掉cpudisk。如果没有,我建议在您的应用程序中查找问题。

答案 1 :(得分:0)

您说

  

有时许多查询不返回   ...无论其他流程如何运作,都会发生这种现象。如果统计   信息错误,查询总是很慢。

当直接连接到Postgres实例并运行所需的查询时,或者从应用程序运行查询时,它们不会返回或变慢。正在运行的后端进程,您是否可以使用pg_terminate_backend($PID)成功终止它们,还是有问题?为了排除语句本身的问题,请确保将statement_timeout设置为合理的值以终止长时间运行的查询。在排除这种情况之后,也许您正在遇到应用程序挂起的情况,并且永远不允许PostgreSQL的send调用完成。为避免出现这种情况,如果您能够(取决于操作系统)可以调整保持活动时间:https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-TCP-KEEPALIVES-IDLE(默认为2小时)

让我们知道是否可以通过任何一种方式进一步了解您的问题。

答案 2 :(得分:0)

很抱歉,如@Konstantin所指出的那样,这可能是由于您的应用程序(这就是为什么我要求您输入EDIT2)的原因。添加一些摘录,

  • table partition对这些锁没有影响,这是一个完全不同的概念,不会针对您的情况保留锁。
  • 在您的应用程序中,检查close()之后read()并正确地终止连接(从Java角度来看),连接是否正确。我不确定您的应用程序层。
  • 检查最近是否错误地编写了SELECT..FOR UPDATE或任何类似的语句。
  • 检查最近是否有任何表的大小已增加,并且该列未建立索引。这是select语句运行几分钟的非常重要且频繁的原因。我还建议对应用程序中的select语句使用timeoutshttps://www.postgresql.org/docs/9.5/gin-intro.html这可以给您带来优势。
  • 让我讨厌的另一件事是JSONB列,也许您的Jsonb值很长,或者即使不需要,查询也不必要选择JSONB值?
  • 最后,如果您不需要Jsonb数据类型的某些特殊功能,则可以使用更快的JSON数据类型(最大魔术数,有时50倍!)

答案 3 :(得分:0)

似乎池中的连接未正确关闭,一些查询可能需要大量时间来回复。如其他答案所指出的,这是应用程序存在的问题,可能是连接泄漏。最有可能的原因可能是由于某些未完成的交易中的未完成交易,导致许多未完成的交易。

此外, PostgreSQL 通常具有一个或多个“ helper ”进程,例如stats collectorbackground writerautovaccum daemonwalsender等,所有这些都显示为“ postgres”实例。

我建议您检查一下启动queries的代码的哪一部分。尝试DRY在应用程序外部运行查询,并获得benchmarking的查询性能。

第二,对于某些查询,如果不是全部,则可以保留一些 超时

第三,您可以在某些超时后使用kill the idle transactions,方法是:

SET SESSION idle_in_transaction_session_timeout = '5min';

我希望它可能会起作用。干杯!

答案 4 :(得分:0)

谢谢大家。

我终于解决了这个问题。 我注意到后端进程持有太多锁。因此,当我执行查询SELECT COUNT(*) FROM pg_locks WHERE pid = <pid>时,结果约为10000。 locks_per_transactions的参数是64,而max_connections的参数是800。 因此,如果拥有许多锁的查询数量很大,则会发生内存不足的情况(如果您有兴趣,请参见PostgreSQL内部共享内存的计算代码)。 当我执行诸如SELECT * FROM (partitioned table)之类的查询时,导致了太多的锁定。 Imangine中有一个已分区的表foo,该表的数量为1000。然后您可以执行SELECT * FROM foo WHERE partion_id = <id>,后端进程将持有约1000个表锁(和索引锁)。因此,我将查询从SELECT * FROM foo WHERE partition_id = <id>更改为SELECT * FROM foo_(partitioned_id)。结果,问题看起来已经解决。