Мощная нестандартная функция, о которой разработчики должны знать
Разве не было бы здорово, если бы мы могли получать уведомления об изменениях, управляемых событиями (ECN), когда данные изменяются непосредственно из базы данных, без необходимости опроса на предмет обновлений?
Эта функция, на самом деле, доступна в некоторых реляционных базах данных, но не во всех, поскольку это нестандартная функциональность и не является частью какой-либо спецификации SQL.
В трех примерах, рассмотренных в этой статье, эта функциональность выражается через реализацию интерфейса, который затем регистрируется непосредственно в драйвере JDBC. Это открывает двери для множества потенциальных вариантов использования, которые могут быть выражены без необходимости опроса и которые не требуют от разработчика написания кода инфраструктуры для обработки изменений в данных и уведомления заинтересованных сторон. Вместо этого мы можем напрямую взаимодействовать с драйвером и прослушивать изменения, а когда они происходят, выполнять любой рабочий процесс, который у нас есть, управляемым событиями способом. Несколько примеров, когда это может быть полезно, включают:
- Кэширование (подробнее об этом, когда мы рассмотрим PostgreSQL, см. Также Хорошие кандидаты для CQN )
- Приманки для таблиц базы данных — также см. ядовитые записи
- Проблемы с отладкой
- Регистрация изменений
- Аналитика и отчетность
Конечно, есть некоторые последствия, когда полагаешься на эту функциональность. Наиболее очевидным следствием является то, что это нестандартная функция, которая напрямую связывает приложение с базой данных.
Я разговаривал с Майклом Дюргнером на LinkedIn о примере реализации, поскольку он относится к PostgreSQL, и он прокомментировал, что :
“Хотя это определенно отличный способ сделать это, одним из больших недостатков является то, что вы переносите логику приложения в СУБД. Не говорю, что вы не должны этого делать, но убедитесь, что у вас есть люди с глубоким пониманием используемой вами СУБД, поскольку маловероятно, что ваше обычное программное обеспечение сможет устранить неполадки. Еще одной огромной проблемой при таком подходе является непрерывная доставка, поскольку ваша СУБД должна быть глубоко интегрирована с вашим конвейером доставки.”
Я согласен с позицией Майкла, и сохранение бизнес-логики вне базы данных, как правило, является хорошей практикой.
Проекты, которые полагаются на инструменты объектно-реляционного сопоставления (ORM), такие как Java Persistence API (JPA) для создания схемы базы данных непосредственно из одной или нескольких объектных моделей, немедленно теряют переносимость и простоту, когда разработчикам требуется добавить логику на уровне базы данных, которая, вероятно, принадлежит самому приложению. Если разработчики не будут осторожны, им в конечном итоге придется использовать для тестирования ту же базу данных, что и в производстве, и это может легко привести к боли и сожалениям.
Я предлагаю следующий вопрос любому инженеру, рассматривающему возможность использования EDCNs через драйвер JDBC: может ли приложение по-прежнему функционировать по назначению без включения того, что вы создаете, которое опирается на эту функциональность? Если ответ “да”, то то, что вы делаете, скорее всего, нормально; напротив, если ответ “нет”, то это удар по использованию EDCNS, и, возможно, потребуется рассмотреть альтернативные варианты.
Наконец, эта функция сама по себе не является заменой хорошо спроектированному ориентированному на сообщения промежуточному программному обеспечению (MOM), который обычно предоставляет готовые решения для гарантированной доставки, сохранения сообщений, доставки по крайней мере один раз/ровно один раз , доставки через очереди и темы, стратегии управления потоком (см. Также: противодавление ) и адреса проблемы отказоустойчивости и масштабируемости. Наличие этих требований может быть убедительным показателем того, что подход, основанный на EDCNs, нуждается в пересмотре.
Ниже мы рассмотрим эту функциональность в том виде, в каком она существует в PostgreSQL , базы данных Oracle и H2 ; мы также включаем некоторые общие замечания по MySQL и его развилка,/| MariaDB .
На протяжении всей этой статьи мы полагаемся на Java 13.0.2 и Groovy. 3.0.4 и включают ссылки на различные скрипты на GitHub, которые содержат дополнительные примечания, касающиеся того, как настроить требуемые зависимости и любые другие предварительные условия, необходимые для запуска примеров.
PostgreSQL
База данных PostgreSQL (Postgres) – это первый пример, который мы рассмотрим.
API Postgres включает в себя интерфейс Notificationlistener , который должен быть реализован, а затем зарегистрирован при подключении к базе данных. Обратите внимание, что доступны две реализации этого: Postgres [default] драйвер JDBC и Невозможная реализация драйвера JDBC . Мы не хотим использовать драйвер Postgres, так как эта реализация будет опрашивать базу данных на предмет изменений. Вместо этого мы будем полагаться на реализацию Impossible, которая обеспечивает настоящие уведомления, управляемые событиями.
У меня была возможность поговорить об этом с Эриком Брандсбергом , техническим директором/| Heimdall Data , и Эрик заметил, что:
“Интерфейс PG notify – одна из скрытых жемчужин PG по сравнению с другими базами данных. Мы можем использовать его для предоставления сообщений о недействительности кэша между прокси-серверами вместо использования отдельного интерфейса pub/sub, например, в Redis.”
Heimdall Data предоставляет сложное решение для кэширования для приложений, использующих Службу реляционных баз данных Amazon (Amazon RDS) и другие базы данных, и это один из реальных примеров использования, который демонстрирует, насколько важной может быть эта функциональность.
В следующем примере триггер и функция скрипт должен выполняться внутри Postgres в качестве предварительного условия для запуска скрипта Groovy. Функция notify_change будет отправлять события всем зарегистрированным слушателям которые прослушивают examplechannel channel — обратите особое внимание на предупреждение ниже, так как имена каналов чувствительны к регистру.
рабочий пример реализации com.impossible.postgres.api.jdbc. Далее включается Notificationlistener с использованием базы данных PostgreSQL. Интерфейс Notificationlistener требует, чтобы разработчик реализовал только один метод:
уведомление о недействительности (идентификатор процесса int, Строковое имя канала, строковая полезная нагрузка)
Мы можем видеть это в строке № 18 ниже.
Мы можем видеть пример выполнения этого скрипта вместе с объяснением и выводом, который появляется в GroovyConsole на следующем изображении.
Объяснение примера PostgreSQL, запущенного в консоли Groovy.
Следующий пример, который мы рассмотрим, включает в себя функциональность уведомления об изменениях, управляемую событиями, поскольку она применяется к Oracle Database .
Оракул
Следующий пример, который мы рассмотрим в этой статье, будет посвящен Базе данных Oracle (Оракул). Ниже мы подробно описываем шаги, необходимые для настройки уведомлений об изменениях, управляемых событиями, с помощью драйвера JDBC, а также предварительные условия, необходимые для запуска примера.
Следующие две сути являются обязательными предварительными условиями для этого примера. Поучительно отметить, что Docker был запущен на другой машине, которая в данном случае использует операционную систему Ubuntu. Смотрите Предупреждение о локальном запуске Oracle в Docker в скрипте DatabaseChangeListener В примере базы данных Oracle.groovy для получения более подробной информации.
В SQL*Plus теперь мы можем запустить следующий сценарий настройки. Имейте в виду, что после создания примерной таблицы, см. строку # 8, можно запустить сценарий Groovy в следующем разделе, и любые операции вставки, обновления или удаления в целевой таблице приведут к отправке события в сценарий Groovy, а затем к выводу на консоль.
Здесь у нас есть пример полного DatabaseChangeListener В Oracle Database Example.groovy script. Обратите внимание, что разработчик должен реализовать один метод:
void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent)
Мы можем видеть эту реализацию в строке # 55 ниже.
На следующем изображении более подробно описывается, что делает каждый шаг, а также некоторые примечания, объясняющие результат.
Более подробное объяснение того, что делает пример сценария, поскольку он относится к базе данных Oracle, включая примечания, объясняющие выходные данные.
Наконец, на следующем рисунке показано, что когда мы выполняем пять вставок подряд, а затем фиксируем изменения, генерируется только одно событие, которое включает в себя эти пять вставок. События генерируются только тогда, когда фиксация завершается успешно.
Пять вставок выполняются в SQL * Plus, за которыми следует одна фиксация, и мы видим, что это событие включает в себя эти пять операций вставки.
Последний пример, который мы рассмотрим в этой статье, включает базу данных H2 .
База данных H2
База данных H2 – это легкая и очень мощная реляционная база данных с открытым исходным кодом, полностью написанная на Java. Он поддерживает длинный список функций и поставляется в виде одного jar-файла объемом 2,2 Мб/| . H2 часто используется при тестировании приложений Java и хорошо работает в качестве встроенной базы данных и может использоваться с инструментами объектно-реляционного сопоставления, такими как Java Persistence API (JPA) . H2 также встроен в сервер приложений JBoss Wildfly (JBoss) и уже очень давно используется в JBoss в качестве встроенной базы данных.
H2 доставляет уведомления о событиях через org.h2.api. Прослушиватель событий базы данных интерфейс. Интерфейс DatabaseEventListener предлагает ограниченную функциональность по сравнению со спецификациями Postgres и Oracle listener, рассмотренными ранее. Методы, необходимые для реализации интерфейса, следующие:
недействительное закрытие базы данных () void exceptionThrown(SQLException SQLException, строка sql) void init (строковый URL-адрес) пустота открыта () void setProgress (Состояние строки, имя строки, int x, int max)
Рабочий пример реализации org.h2.api. Прослушиватель событий базы данных с использованием базы данных H2 можно найти на GitHub и также включен в суть ниже, за которым следует изображение с указателями, объясняющими, как это работает.
В этом примере H2 выполняется во встроенном режиме, то есть H2 выполняется полностью в памяти на той же виртуальной машине, на которой выполняется сценарий Groovy.
На следующем изображении мы можем видеть пример выполнения этого скрипта вместе с выводом в GroovyConsole.
Пример прослушивателя событий базы данных H2, запущенного в консоли Groovy, включая вывод.
Несколько разочаровывает тот факт, что прослушиватель событий базы данных H2 не предлагает аналогичной функциональности, которую можно найти в интерфейсе PostgreSQL. В результате я отправил запрос на новую функцию в репозитории базы данных H2 на GitHub и, возможно, попытаюсь реализовать это самостоятельно, если позволит время.
MySQL/MariaDB
Уведомления об изменениях, управляемые событиями, через драйвер JDBC, по-видимому, не поддерживаются ни базами данных MySQL, ни MariaDB, поэтому инженерам придется рассмотреть альтернативные решения, если требуется эта функциональность.
Мы не будем рассматривать триггеры и пользовательские функции (UDF), поскольку они относятся к MySQL и MariaDB для вызова конечной точки веб-службы, которая является одной из таких альтернатив. Краткое исследование по этому вопросу предполагает, что для достижения этой цели можно использовать триггеры и UDFS; однако они сопряжены с потенциально значительными последствиями для безопасности и производительности, которые необходимо учитывать при использовании этого подхода.
Если вы использовали триггеры и UDFs или какое-либо другое решение для достижения этой цели в MySQL и/или MariaDB, пожалуйста, не стесняйтесь подробно рассказать о том, что вам нужно было сделать, какой подход вы использовали, и насколько хорошо это сработало в комментариях. Наконец, если есть лучшее решение, доступное в MySQL и MariaDB, пожалуйста, объясните подробнее.
Вывод
Использовали ли вы управляемые событиями уведомления об изменениях в реляционных базах данных в проекте, над которым вы работали? Если это так, я призываю вас обсудить любое из следующих вопросов в комментариях:
- Для чего это было нужно?
- Какая база данных использовалась?
- На каком языке было написано решение?
- Можете ли вы сделать это с помощью Microsoft SQL Server или другой базы данных, не описанной здесь?
- Возникали ли какие-либо проблемы и как они решались?
- Был ли этот вариант изучен и определен как не подходящее решение для рассматриваемой проблемы?
- Были ли вы вынуждены использовать альтернативу, и если да, то как выглядела реализация и почему?
- Любые другие мысли, которые у вас могут возникнуть, включая любые вопросы, которые я, возможно, оставил здесь.
Хотя Edge предлагает мощную функциональность в поддерживаемых реляционных базах данных, мы надеемся, что в дополнение к предоставлению некоторых рабочих примеров также было ясно, что использование этой функции сопряжено с определенными затратами и что вы должны должным образом рассмотреть ее перед использованием.
Счастливого кодирования!
Если вы сочли этот документ полезным, вы также можете найти Группу встреч главного технического директора в Вашингтоне, округ Колумбия также полезной. Мы часто проводим мероприятия, и поскольку они доступны через Zoom, локальность в районе DC не является обязательным требованием.
Смотрите также:
- Технический директор района метро Вашингтона Slack Сообщество ( альтернативная ссылка здесь )
- Технический директор по метрополитену округа Колумбия (технический директор) сеть LinkedIn Группа
Изображение на обложке комплименты Крис Коу
Оригинал: “https://dev.to/coherentlogic/hidden-gems-event-driven-change-notifications-in-relational-databases-23gn”