Python 中使用 Psycopg2 维护与 PostgreSQL 的连续连接的最佳实践

206 阅读4分钟

在编写一个 Python 应用,它使用了 PostgreSQL 8.3,并运行在本地网络上的多台机器上。所有机器:

1)从数据库服务器获取大量数据(假设一台机器在 2 秒内向数据库发送 100 个不同的查询),并且大约有 10 或 11 台机器正在这样做。 2)在处理完数据后,机器必须更新某些表(每台机器每 1.5 秒大约有 3 或 4 个更新/插入查询)。

我注意到的是,数据库有时会宕机,表现为服务器异常中止进程,或者冻结服务器机器(需要硬重置)。顺便说一下,所有机器都始终与数据库保持恒定连接,也就是说,一旦使用 Psycopg2(在 Python 中)建立连接后,它会一直保持活动状态,直到处理完成(可能持续数小时)。

对于应用程序中处理大量连接的最佳/最优方法是什么,是否应该在每次查询后销毁它们?其次,我是否应该增加 max_connections?非常感谢您对此事的任何建议。

2、解决方案

答案 1:

这听起来有点像是你的数据库服务器可能存在一些问题,尤其是如果你的数据库服务器确实崩溃了。我会先尝试从日志中找出问题的根本原因。这可能像内存不足,但也可能因为硬件故障而发生。

如果你在启动时打开所有连接并保持打开状态,则 max_connections 不是罪魁祸首。你处理数据库连接的方式应该是好的,无论其配置如何,你的服务器都不应该这样做。

答案 2:

最可能的原因听起来确实像是内存不足。如果这些是 Linux 服务器,则触发内存不足现象会调用“OOM-killer”,它只是终止内存占用很大的进程(因此“服务器进程异常中止”)。内存不足的情况通常意味着非常高的磁盘交换/分页负载,这使得服务器看起来没有响应。

在你的内核日志文件(或 dmesg 命令)中查看任何类似“内存不足:已杀死进程 1234 (postgres)”的内容。这是由允许内核超量分配内存的默认值引起的。你应该做的第一件事是禁用超量分配,以便对内存不足情况进行优雅处理:

echo 2 > /proc/sys/vm/overcommit_memory

方案 A:

一个可能的罪魁祸首是 work_mem 设置,它指定每个单独的操作可以分配多少内存。一个查询可能包含多个内存密集型步骤,因此每个后端可以分配几倍于 work_mem 数量的内存,除了全局 shared_buffers 设置之外。此外,你还需要一些空闲内存用于操作系统缓存。

有关更多信息,请参阅 PostgreSQL 关于资源消耗设置的手册:PostgreSQL 8.3 Documentation, Resource Consumption

方案 B:

可能会减少这些可调整参数会使你的查询速度变慢,以至于你仍然无法完成工作。另一种方法是人为地限制可以并行运行的查询数量。许多用于 PostgreSQL 的连接池中间件可以限制并行查询的数量,并提供队列。这种软件的示例包括 pgbouncer(更简单)和 pgpool-II(更灵活)。

编辑:回答你的问题:

对于应用程序中处理大量连接的最佳/最优方法是什么,是否应该在每次查询后销毁它们?

通常,建立与 PostgreSQL 的新连接并不快,因为 PostgreSQL 为每个后端生成一个新进程。但是,就内存而言,进程并不便宜,因此保持许多空闲连接到数据库并不是一个好主意。

我 在方案 B 中提到的连接池中间件将负责保持一定数量的连接到 Postgres——无论你何时或多久连接或断开连接。因此,如果你选择该方式,你无需担心手动打开/关闭连接。

其次,我是否应该增加 max_connections ?

除非你的数据库服务器具有大量 RAM(超过 8GB),否则我不会超过 100 个连接的默认限制。