Найти в Дзене
Nuances of programming

Скрытые алмазы: уведомления об изменениях в БД

Оглавление

Источник: Nuances of Programming

Вступление

Получение управляемых событиями уведомлений об изменениях (EDCN), когда данные изменяются непосредственно из БД, без необходимости опроса для получения обновлений — очень эффективная функциональность. Подобная доступна в некоторых реляционных БД, но не во всех, так как она нестандартная и не является частью спецификации SQL.

В примерах ниже она выражается через реализацию интерфейса, который регистрируетсянепосредственно драйвером JDBC. Это открывает множество потенциальных вариантов применения, которые можно выразить без опроса, кода инфраструктуры для обработки изменений данных и уведомления заинтересованных сторон. Можно взаимодействовать с драйвером напрямую и слушать изменения, а когда они происходят, выполнять работу, управляемую событиями. Примеры:

  • Кэширование (подробнее об этом, когда мы рассмотрим PostgreSQL, см. Good Candidates for CQN).
  • Honeypots для таблиц БД.
  • Проблемы отладки.
  • Протоколирование изменений.
  • Аналитика и отчетность.

Но здесь есть свои последствия. Эта нестандартная функция связывает приложение напрямую с БД.

Майкл Дюргнер о примере реализации в PostgreSQL:

Недостаток заключается в том, что вы перемещаете логику приложения в СУБД. Убедитесь, что у вас есть люди с пониманием вашей СУБД, потому что обычное ПО не сможет справиться с проблемами типа непрерывной доставки. СУБД должна быть глубоко интегрирована с этим процессом.

И я с ним согласен — необходимо сохранять бизнес-логику вне БД.

Проекты, использующие инструменты объектно-реляционного отображения (ORM), такие как Java Persistence API (JPA) для генерации схемы БД непосредственно из одной или нескольких объектных моделей, теряют мобильность и простоту, когда разработчикам требуется добавлять логику на уровне БД, принадлежащую самому приложению. Им приходится использовать ту же БД для тестирования, что и при разработке, а это, в свою очередь, может привести к проблемам.

Может ли приложение функционировать без создаваемого вами ПО, которое требует работы EDCN через драйвер JBDC? Если “да” ,— прекрасно, если “нет”, то это аргумент против EDCN и необходимо подумать, прежде чем применять его.

Эта функция сама по себе не является заменой хорошо спроектированного промежуточного ПО, ориентированного на сообщения (MOM), которое предоставляет готовые решения для гарантированной доставки, сохранения сообщений, доставки хотя-бы-один-раз/строго-однократной через очереди и темы, стратегий управления потоком и решения проблем отказоустойчивости и масштабируемости. Наличие каких-то из этих пунктов показывает, что EDCN-подход нуждается в пересмотре.

Рассмотрим функциональность в том виде, в котором она существует в PostgreSQL, Oracle и H2, и прокомментируем MySQL и его форк MariaDB.

Работаем с Java 13.0.2 и Groovy 3.0.4, также есть ссылки на скрипты на GitHub, которые содержат дополнительные примечания, касающиеся настройки необходимых зависимостей и других требований для примеров.

PostgreSQL

API Postgres включает в себя интерфейс PGNotificationListener, который нужно реализовать и затем зарегистрировать при соединении с БД. Есть две доступные реализации: [по умолчанию] драйвер Postgres и драйвер Impossibl JDBC. Драйвер Postgres будет опрашивать БД на предмет изменений  —  не будем его использовать. Полагаемся на реализацию Impossibl, которая обеспечивает настоящие уведомления, управляемые событиями.

Эрик Брандсберг (Heimdall Data):

“Интерфейс PG notify  —  это один из скрытых алмазов в PG. Мы применяем его для доставки сообщений о недействительности кэша между прокси-серверами вместо отдельного интерфейса pub/sub, как в Redis.”

Heimdall Data предоставляет сложное решение для кэширования приложений, использующих Amazon Relational Database Service (Amazon RDS) и других БД, а это показывает важность такой функции.

Ниже скрипт триггера и функции должен быть выполнен внутри Postgres в качестве предварительного условия для запуска скрипта Groovy. Функция notify_change будет отправлять события всем зарегистрированным слушателям, которые работают с каналом examplechannel (предупреждение: имена каналов чувствительны к регистру).

Рабочий пример реализации com.impossibl.postgres.api.jdbc. PGNotificationListener с использованием PostgreSQL включен далее. Интерфейс PGNotificationListener требует, чтобы разработчик реализовал один метод:

void notification(int processId, String channelName, String payload)

Это можно увидеть на строке 18:

Пример выполнения вместе с объяснением и выводом в GroovyConsole:

Объяснение примера PostgreSQL, запущенного в консоли Groovy.
Объяснение примера PostgreSQL, запущенного в консоли Groovy.

Oracle

Следующий пример будет посвящен Oracle. Ниже шаги, необходимые для настройки уведомлений об изменениях, управляемых событиями, с помощью драйвера JDBC, а также условия для примера.

Важно, чтобы Docker работал на другой машине, которая в данном случае использует Ubuntu. Детальное предупреждение о локальном запуске Oracle в Docker в скрипте DatabaseChangeListenerInOracleDatabaseExample.groovy.

В SQL*Plus можно запустить скрипт конфигурации. После создания примера таблицы (см. строку 8) в следующем разделе можно запустить скрипт Groovy, и любые операции вставки, обновления или удаления в целевой таблице приведут к тому, что событие будет отправлено в скрипт Groovy, а затем на вывод.

Пример полного скрипта DatabaseChangeListenerInOracleDatabaseExample.groovy. Разработчик должен реализовать один метод:

void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent)

Можно увидеть эту реализацию в строке 55:

О том, что делает каждый шаг:

Пример скрипта, относящегося к Oracle, включая примечания, объясняющие выходные данные.
Пример скрипта, относящегося к Oracle, включая примечания, объясняющие выходные данные.

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

SQL*Plus: генерируется событие, которое включает в себя эти операции вставки.
SQL*Plus: генерируется событие, которое включает в себя эти операции вставки.

Н2

Это открытая, легкая и мощная реляционная БД, написанная на Java. Она поддерживает много функций и поставляется в виде одного jar-файла размером 2,2 Мб. H2 часто используется при тестировании Java-приложений и хорошо работает в качестве встроенной БД, а также может использоваться с инструментами объектно-реляционного отображения, такими как Java Persistence API (JPA). H2 встроен в сервер приложений JBoss Wildfly (JBoss) и давно используется в JBoss в качестве встроенной БД.

H2 доставляет уведомления о событиях через интерфейс org.h2.api.DatabaseEventListener. DatabaseEventListener предлагает ограниченную функциональность по сравнению со прослушивателями Postgres и Oracle, рассмотренными ранее. Методы, необходимые для реализации интерфейса:

void closingDatabase ()
void exceptionThrown(SQLException sqlException, String sql)
void init (String url)
void opened ()
void setProgress (String state, String name, int x, int max)

Пример реализации org.h2.api.DatabaseEventListener, применяющий H2, можно найти на GitHub,а также он описан ниже.

В примере H2 работает во встроенном режиме  —  то есть полностью в памяти на той же виртуальной машине со сценарием Groovy.

Пример выполнения вместе с объяснением и выводом из GroovyConsole:

Пример H2 DatabaseEventListener, работающего в Groovy.
Пример H2 DatabaseEventListener, работающего в Groovy.

DatabaseEventListener H2 не предлагает аналогичную функциональность, как в PostgreSQL. Вот запрос на новую функцию в репозиторий БД H2 на GitHub.

MySQL/MariaDB

Управляемые событиями уведомления об изменениях через драйвер JDBC не поддерживаются ни MySQL, ни MariaDB, поэтому придется подумать об альтернативах.

Не будем рассматривать триггеры и пользовательские функции (UDF), поскольку они относятся к MySQL и MariaDB для вызова конечной точки веб-службы, которая и является одной из альтернатив. Их можно использовать, однако потенциально это будет иметь последствия для безопасности и производительности.

Вывод

Хотя EDCN предлагает мощные функции в поддерживаемых реляционных БД, у этого метода есть цена, описанная в рабочих примерах, о которой надо подумать.

Читайте также:

Читайте нас в Telegram, VK

Перевод статьи Thomas P. Fuller: Hidden Gems: Event-Driven Change Notifications in Relational Databases