如何最好地在SQLAlchemy中将连接池用于PgBouncer事务级池?


15

使用SQLAlchemy通过事务级池在PgBouncer后面查询PostgreSQL数据库。

进行这种设置的最佳模式是什么?我ConnectionPool应该使用NullPool来为每个进程分配一个引擎,还是应该为每个请求创建一个引擎,并针对每个请求使用一个引擎?我应该使用完全不同的模式吗?

非常感谢!让我知道是否需要更多信息,我将尽快更新。

Answers:


9

使用PGBouncer,您可能只想坚持使用NullPool。在这种情况下,由于子进程边界上没有套接字连接,因此您可能能够在子进程之间共享单个引擎。但是您不能在此边界上共享任何引用Connection对象的内容,例如具有有效事务的Session。但是,您绝对不希望执行“每个请求的引擎”,因为Engine是一种昂贵的对象,它在第一次看到特定数据库URL时会积累许多信息。


4

设置应用名称

如果您希望运行许多进程,则需要知道它们从何处连接。PGBouncer将使它不可见pg_stat_activity。通过仔细设置所需application_name的信息来解决此问题:

# Sets the application name for this connection in the form of
#   application-name:user@host
prog = os.path.basename(sys.argv[0]) or 'desjob'
username = pwd.getpwuid (os.getuid ()).pw_name
hostname = socket.gethostname().split(".")[0
args.setdefault('connect_args', {'application_name': "%s:%s@%s" %
    (prog, username, hostname)})
args.setdefault('isolation_level', "AUTOCOMMIT")
engine = create_engine(url, **args)

优先会议

使用会话是因为来自Engine对象的请求可以产生并保持多个连接。连接到Postgres并不是很昂贵,而使用PGBouncer则更便宜。我会一直使用,NullPool以便您在Postgres中看到的唯一连接是实际使用的连接。

from sqlalchemy.pool import Pool, NullPool
engine = create_engine(uri, poolclass=NullPool)

消除闲置交易

如果您打算使用PGBouncer进行扩展,则必须避免使事务处于打开状态。要做到这一点,你需要打开autocommit 。对于SQLAlchemy来说,这并不简单...可以在三个地方设置“自动提交”:

psycopg2自动提交

conn = psycopg2.connect(uri)
conn.autocommit = True

假定不安全是不安全的,因为SQLAlchemy需要知道下面发生了什么。

会话自动提交

Session = sessionmaker(bind=engine, autocommit=True)
session = Session()

这需要仔细,明确的处理:

session.begin()
session.execute(...)
session.rollback()

函数调用和异常处理非常困难,因为 begin()并且commit()不能嵌套:

def A():
  session.begin()
  ...
  session.rollback()

def B():
  session.begin()
  try:
      A() # error, already open

在此模式下,psycopg2 autocommit似乎是False(默认值)

引擎自动提交

"AUTOCOMMIT"在创建引擎时将引擎隔离模式设置为可以建立新的默认行为,该行为可能不需要更改现有代码。

engine = create_engine(uri, isolation_level="AUTOCOMMIT")

在此模式下,psycopg2 autocommit似乎是True

这里的主要问题是,保证代码块包装在事务中的唯一方法是手动发出语句:

session.execute("BEGIN")
#...
session.execute("COMMIT")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.