首页 > 解决方案 > 从 pg_stat_activity 收集 postgres pids/backends 在一个会话中返回恒定结果

问题描述

在一个具有隔离级别READ_COMMITTED的会话中,活动 pid 的列表pg_stat_activity只收集一次,下一次尝试返回相同的结果。有谁可以解释为什么?

重现该现象的脚本:

#!/usr/bin/env python

import time

from sqlalchemy.engine import create_engine
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.pool import NullPool

pg_uri = 'postgresql://test:test@localhost:5432/test'


def get_session():
    bind = create_engine(pg_uri, poolclass=NullPool, echo=False, isolation_level="READ_COMMITTED")
    session_class = sessionmaker(bind=bind)
    return session_class()

def pg_sleep():
    get_session().execute('select pg_sleep(3)')


def show_backends(session, prefix):
    backends = session.execute("SELECT pid, query FROM pg_stat_activity where state = 'active';").fetchall()
    print ("%s found processes:" % prefix)
    for backend in backends:
        print("%s: %s %s" % (prefix, backend[0], backend[1][:32]))


def spawn_backend():
    import threading
    print("spawning backend")
    threading.Thread(None, target=pg_sleep).start()
    show_backends(get_session(), 'thread')


session = get_session()
for tries in range(3):
   spawn_backend()
   time.sleep(1)
   show_backends(session, '-main-')

我在用着:

postgresql-9.6
Python 2.7.12
SQLAlchemy 1.1.12 

标签: pythonpostgresqlsqlalchemy

解决方案


关于监控统计的文档说:

另一个重要的一点是,当要求服务器进程显示任何这些统计信息时,它首先获取收集器进程发出的最新报告,然后继续将此快照用于所有统计视图和函数,直到其当前事务结束. 因此,只要您继续当前事务,统计信息就会显示静态信息。同样,当在事务中首次请求任何此类信息时,将收集有关所有会话的当前查询的信息,并且将在整个事务中显示相同的信息。这是一项功能,而不是错误,因为它允许您对统计信息执行多个查询并关联结果,而不必担心您下面的数字会发生变化。但是,如果您想查看每个查询的新结果,确保在任何事务块之外进行查询。或者,您可以调用 pg_stat_clear_snapshot(),这将丢弃当前事务的统计快照(如果有)。下次使用统计信息将导致获取新的快照。

请考虑pg_stat_clear_snapshot在您的代码中使用。


推荐阅读