Ожидание обновления строки или вставки строки с помощью sqlalchemy

#python #postgresql #sqlalchemy

#python #postgresql #sqlalchemy

Вопрос:

У меня есть приложение, которое отображает содержимое базы данных, которая обновляется каждые 5-10 минут. Загрузка всех данных в базу данных занимает около 5 минут. Вместо того, чтобы перезагружать все данные в базе данных при каждом обновлении, я хотел бы загружать только новые строки или поля строк, которые были обновлены.

  1. Можно ли проверить наличие измененных или новых полей с помощью sqlalchemy (для опроса изменений)?
  2. Возможно ли дождаться измененных или новых полей с помощью sqlalchemy (с вызовом блокирующей функции)?

База данных — это база данных postgres, если это имеет значение.

Ответ №1:

В ProstgeSQL есть механизм NOTIFY / LISTEN, который можно использовать с триггерами для отправки уведомлений о вставке, удалении и обновлении. Уведомление включает в себя аргумент, такой как таблица и действие.

Не похоже, что SQLAlchemy поддерживает эту функциональность, вероятно, поскольку это не стандарт SQL, а специфичный для Postgres.

Вот пример проверки изменений в базе данных prostgres с помощью NOTIFY / LISTEN с использованием python: PostgreSQL ПРОСЛУШИВАЕТ / УВЕДОМЛЯЕТ

Поиск в Google NOTIFY in PostgreSQL and python может предоставить дополнительную помощь.

Ответ №2:

SQLAlchemy напрямую не поддерживает ПРОСЛУШИВАНИЕ / УВЕДОМЛЕНИЕ Postgres, но вы можете получить доступ к нему через psycopg2, что затем дает вам такую возможность: http://initd.org/psycopg/docs/advanced.html#async-notify

(Я понял это из этой сути: https://gist.github.com/dtheodor/3862093af36a1aeb8104 )

Psycopg2 может выполнять полностью асинхронную доставку уведомлений. Лично мне не очень повезло с этим внутри SQLAlchemy, и я подозреваю, что это слишком низкий уровень для их поддержки. Однако в документах приведен приведенный ниже пример, в котором используется select() для ожидания, пока соединение сообщит, что что-то происходит, а затем использует poll(), чтобы узнать, есть ли уведомление.

 import select
import psycopg2
import psycopg2.extensions

conn = psycopg2.connect(DSN)
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)

curs = conn.cursor()
curs.execute("LISTEN test;")

print "Waiting for notifications on channel 'test'"
while 1:
    if select.select([conn],[],[],5) == ([],[],[]):
        print "Timeout"
    else:
        conn.poll()
        while conn.notifies:
            notify = conn.notifies.pop(0)
            print "Got NOTIFY:", notify.pid, notify.channel, notify.payload
  

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

Один из таких вариантов использования — когда вы используете NOTIFY, чтобы сообщить вам об обновляемой таблице. Вы устанавливаете время ожидания на что-то довольно долгое. Если вы получаете УВЕДОМЛЕНИЕ или тайм-аут, вы делаете ВЫБОР, чтобы увидеть, что изменилось в таблице. Таким образом, вы сделаете это сразу, если получите УВЕДОМЛЕНИЕ, но в конечном итоге сделаете это в любом случае, даже если вы этого не сделаете.