Пример пула соединений в PostgreSQL с помощью Psycopg2

В этом материале рассмотрим понятие пула соединений и особенности его реализации для базы данных PostgreSQL в Python с помощью Psycopg2.

Пул соединений — это кэшированные соединения с базой данных, которые создаются и поддерживаются таким образом, чтобы не было необходимости пересоздавать их для новых запросов.

Реализация и использование пула соединений в приложении Python, работающим с базой данных PostgreSQL, дает несколько преимуществ.

Основное — улучшение времени и производительности. Как известно, создание соединения с базой данных PostgreSQL — операция, потребляющая ресурсы и время. А с помощью пула можно уменьшить время запроса и ответа для приложений, работающих с базой данных в Python. Рассмотрим, как его реализовать.

В модуле psycopg2 есть 4 класса для управления пулом соединений. С их помощью можно легко создавать пул и управлять им. Как вариант, того же результата можно добиться с помощью реализации абстрактного класса.

Классы psycopg2 для управления пулом соединений

В модуле psycopg2 есть четыре класса для управления пулом соединений:

  • AbstractConnectionPool.
  • SimpleConnectionPool.
  • ThreadedConnectionPool.
  • PersistentConnectionPool.

Примечание: SimpleConnectionPool, ThreadedConnectionPool и PersistentConnectionPool являются подклассами AbstractConnectionPool и реализуют методы из него.

Рассмотрим каждый из них по отдельности.

AbstractConnectionPool

Это базовый класс, реализующий обобщенный код пула, основанный на ключе.

psycopg2.pool.AbstractConnectionPool(minconn, maxconn, *args, **kwargs)

AbstractConnectionPool — это абстрактный класс. Наследуемые должны реализовывать объявленные в нем методы. Если хотите создать собственную реализацию пула соединений, то нужно наследоваться от него и реализовать эти методы.

minconn — это минимальное требуемое количество объектов соединения. *args, *kwargs — аргументы, которые нужны для метода connect(), отвечающего за подключение к базе данных PostgreSQL.

SimpleConnectionPool

Это подкласс AbstractConnectionPool, реализующий его методы. Его уже можно использовать для пула соединений.

Этот класс подходит только для однопоточных приложений. Это значит, что если вы хотите создать пул соединений с помощью этого класса, то его нельзя будет передавать между потоками.

Синтаксис:

psycopg2.pool.SimpleConnectionPool(minconn, maxconn, *args, **kwargs)

ThreadedConnectionPool

Он также является подклассом класса AbstractConnectionPool и реализует его методы.

Этот класс используется в многопоточной среде, т.е. пул, созданный с помощью этого класса, можно разделить между несколькими потоками.

psycopg2.pool.ThreadedConnectionPool(minconn, maxconn, *args, **kwargs)

PersistentConnectionPool

Еще один подкласс AbstractConnectionPool, реализующий его методы.

Этот класс используется в многопоточных приложениях с пулом, распределяющим постоянные соединения разным потокам.

Как и предполагает название, каждый поток получает одно соединение из пула. Таким образом, у одного потока может быть не больше одного соединения из пула.

Пул соединений генерирует ключ с помощью идентификатора потока. Это значит, что для каждого потока при вызовах соединение не меняется.

Примечание: этот класс преимущественно предназначен для взаимодействия с Zope и, вероятно, не подходит для обычных приложений.

Синтаксис:

psycopg2.pool.PersistentConnectionPool(minconn, maxconn, *args, **kwargs)

Посмотрим, как создать пул соединений.

Методы psycopg2 для управления пулом соединений

Следующие методы представлены в модуле Psycopg2 и используются для управления.

  • getconn(key=None) — для получения доступного соединения из пула. Параметр key необязательный. При использовании этого параметра getconn() возвращает соединение, связанное с этим ключом. Key используется в классе PersistentConnectionPool.
  • putconn(connection, key=None, close=False) — для возвращения соединения обратно в пул. Если параметр close равен True, то соединение удаляется и из пула. Если при получении соединения был использован ключ, то его же нужно передать при возвращении соединения.
  • closeall() — закрывает все используемые соединения пула.

Создание пула соединений с помощью psycopg2

В этом примере используем SimpleConnectionPool для создания пула. Перед этим стоит рассмотреть аргументы, которые требуются для работы.

Нужно указать минимальное и максимальное количество соединений, имя пользователя, пароль, хост и базу данных.

  • minconn — это нижний лимит количества подключений.
  • maxconn — максимальное количество возможных подключений.
  • *args, **kwargs — аргументы для метода connect(), необходимые для создания объекта соединений. Тут требуется указать имя хоста, пользователя, пароль, базу данных и порт.

Пример создания и управления пулом соединений PostgreSQL

Рассмотрим, как использовать класс SimpleConnectionPool для создания и управления пулом соединений из Python.

import psycopg2
from psycopg2 import pool


try:
    # Подключиться к существующей базе данных
    postgresql_pool = psycopg2.pool.SimpleConnectionPool(1, 20,
                                  user="postgres",
                                  # пароль, который указали при установке PostgreSQL
                                  password="1111",
                                  host="127.0.0.1",
                                  port="5432",
                                  database="postgres_db")

    if postgresql_pool:
        print("Пул соединений создан успешно")
        
    # Используйте getconn() для получения соединения из пула соединений.
    connection = postgresql_pool.getconn()

    if connection:
        print("Соединение установлено")
        cursor = connection.cursor()
        cursor.execute("select * from mobile")
        mobile_records = cursor.fetchall()

        print ("Отображение строк с таблицы mobile")
        for row in mobile_records:
            print(row)

        cursor.close()

        # Используйте этот метод, чтобы отпустить объект соединения
        # и отправить обратно в пул соединений
        postgresql_pool.putconn(connection)
        print("PostgreSQL соединение вернулось в пул")

except (Exception, psycopg2.DatabaseError) as error :
    print ("Ошибка при подключении к PostgreSQL", error)
finally:
    if postgresql_pool:
        postgresql_pool.closeall
    print("Пул соединений PostgreSQL закрыт")

Вывод:

Пул соединений создан успешно
Соединение установлено
Отображение строк с таблицы mobile
(1, 'IPhone 12', 800.0)
(2, 'Google Pixel 2', 900.0)
PostgreSQL соединение вернулось в пул
Пул соединений PostgreSQL закрыт

Разберем пример. В метод были переданы следующие значения:

  • Minimum connection = 1. Это значит, что в момент создания пула создается как минимум одно соединение.
  • Maximum connection = 20. Всего можно использовать 20 соединений с PostgreSQL.
  • Другие параметры для подключения.
  • Конструктор класса SimpleConnectionPool возвращает экземпляр пула.
  • С помощью getconn() делается запрос на подключение из пула
  • После этого выполняются операции в базе данных.
  • И в конце закрываются все активные и пассивные объекты соединения для закрытия приложения.

Создание многопоточного пула соединений

Создадим пул соединений, который будет работать в многопоточной среде. Это можно сделать с помощью класса ThreadedConnectionPool.

import psycopg2
from psycopg2 import pool

try:
    # Подключиться к существующей базе данных
    postgresql_pool = psycopg2.pool.ThreadedConnectionPool(5, 20,
                                  user="postgres",
                                  # пароль, который указали при установке PostgreSQL
                                  password="1111",
                                  host="127.0.0.1",
                                  port="5432",
                                  database="postgres_db")

    if postgresql_pool:
        print("Пул соединений создан успешно")
        
    # Используйте getconn() для получения соединения из пула соединений.
    connection = postgresql_pool.getconn()

    if connection:
        print("Соединение установлено")
        cursor = connection.cursor()
        cursor.execute("select * from mobile")
        mobile_records = cursor.fetchall()

        print ("Отображение строк с таблицы mobile")
        for row in mobile_records:
            print(row)

        cursor.close()

        # Используйте этот метод, чтобы отпустить объект соединения
        # и отправить обратно в пул соединений
        postgresql_pool.putconn(connection)
        print("PostgreSQL соединение вернулось в пул")

except (Exception, psycopg2.DatabaseError) as error :
    print ("Ошибка при подключении к PostgreSQL", error)
finally:
    if postgresql_pool:
        postgresql_pool.closeall
    print("Пул соединений PostgreSQL закрыт")

Вывод будет таким же:

Создание многопоточного пула соединений

Обучение с трудоустройством

Профессия Python-разработчик

Профессия Python-разработчик

7 820 4 692 ₽/мес.
Профессия Data Scientist

Профессия Data Scientist

11 520 6 912 ₽/мес.
Профессия Python Fullstack

Профессия Python Fullstack

7 820 4 692 ₽/мес.
Профессия Data Science: Аналитик

Профессия Data Science: Аналитик

6 600 3 960 ₽/мес.

Появились вопросы? Задайте на Яндекс.Кью

У сайта есть сообщество на Кью >> Python Q <<. Там я, эксперты и участники отвечаем на вопросы по python и программированию.