Database as Сode. Копаем глубже

cffc531ceba649ce936b1abc5c31b7bc.jpg

В IT-проектах код пишут все. Инженеры с помощью нескольких строк управляют Kubernetes кластерами, разгоняют облака Terraform’ом и ворочают тонны конфигураций на Ansible, Chef и Puppet. QA пишут понятные бизнесу тестовые сценарии на Spock и Cucumber. Аналитики свободно, часто лучше разработчиков, разговаривают на SQL. Проектная документация в форматах Markdown, AsciiDoc или LaTEX «компилируются» в нужный формат на билд-сервере. Ну, а сами разработчики, эти укротители кода, владеют сразу россыпью языков на каждый жизненный случай — клиентский, серверный, скриптовый, функциональный и пр.

Код уже давно перестал быть загадочной тарабарщиной и теперь в том или ином виде доступен и понятен многим, даже премьер-министрам. И весь этот код участвует в стандартном жизненном цикле — находится под управлением VCS, подвергается code review, автоматизированному тестированию, CI, CD. Используются общие инструменты и подходы, метрики производительности и качества. А все вместе это носит гордое название — «Everything as code».

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

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

В связи с этим давно появился и успешно используется подход Polyglot Persistence, в результате чего встретить в наши дни на каком-нибудь проекте одну единственную СУБД будет большой удачей. Вместо этого для каждой конкретной задачи подбирается наиболее подходящая база, без попыток как-то выкрутиться и решить все свои проблемы на старой доброй реляционке. А, например, микросервисная архитектура позволяет изолировать работу с конкретной СУБД в рамках одного сервиса и выжать из нее максимум пользы, без вреда для чистоты архитектуры всего проекта. В итоге »Реляционка» (куда ж без неё) + »Key-value DB» + »Wide Column DB» + »Document-oriented DB» + »Search engine DB» + »Graph DB» + »Какая-то еще DB» = »SUCCESS! ». Помимо этого, увеличивается количество экземпляров (инстансов) этих БД — шардинг, репликации, распределенные СУБД. Плюс все это надо «растянуть» и поддерживать в разных средах — разработческой, тестовой, продовой и пр.

Чтобы не быть голословным, приведу несколько выдержек из свежего соцопроса от компании-гиганта по решениям в области управления и разработки БД Quest Software — Проблемы DBA: Тренды в администрировании БД (чтобы скачать, придется пройти несложную регистрацию, но оно того стоит):


  • Вопрос №2:»Сколько инстансов реляционных БД запущено в вашей компании? » — по результатам 24% респондентов используют от 100 до 500 инстансов, а 19% более 500.
  • Вопрос №4:»Сколько различных СУБД (SQL и NoSQL) используется в вашей компании? » — 56% используют от 2-х до 3-х различных СУБД, 40% более 5-и, и только у 4% опрошенных одна-единственная СУБД.
  • Вопрос №18:»Что происходит с количеством инстансов БД в ваших проектах? » — 2/3 респондентов отмечают ежегодное их увеличение.
  • Вопрос №30 (в качестве итога):»С какими главными проблемами столкнутся DBA в ближайшие 3 года? »
    1. 51% — »Увеличение количества инстансов СУБД»
    2. 40% — »Возможность администрировать новые нереляционные БД»
    3. 32% — »Сокращение IT-бюджета» (который, ожидаемо, распухает из-за первых двух проблем)

Не секрет, что для эффективной работы с той или иной СУБД необходимы специализированные инструменты, такие, как IDE и DB-менеджеры, средства мониторинга, моделирования, миграции схем и многое другое. Однако большая часть таких инструментов и сред были придуманы и разработаны еще в те славные времена, когда любому проекту с головой хватало одной-единственной реляционной СУБД, а таких модных слов, как »Agile»,»DevOps» и »CI/CD», еще не придумали. И с тех пор мало что изменилось, т.к. область разработки и сопровождения БД всегда являлась достаточно закрытой и консервативной, а у большинства разработчиков ассоциируются с чем-то древним, сложным и непонятным. Сегодня же, когда практически в любом проектном хозяйстве трудится сразу несколько самых разношерстных СУБД и десятки/сотни их инстансов, обычные повседневные проблемы разработчиков и DBA становятся еще более острыми.

Традиционно самым популярным и незаменимым инструментом для работы с БД являются всевозможные IDE. Обычно это комплексное решение, которое объединяет под своим интерфейсом, в основном графическим, самые разные функции для разработки и администрирования в единую рабочую среду, делает нашу работу с БД более продуктивной и комфортной — остается только клацнуть мышью на нужном пункте меню. И действительно, мало кто из нас обходится без таких крутых штук, как EMS SQL Manager, Toad, dbForge и многих других.

Одной из главных проблем таких «коробочек» является то, что под прессом новых фич и новых СУБД (которые не прекращают появляться на рынке) они получаются довольно сложными и продолжают усложняться с каждым разом. Причем как в использовании (зачастую людям приходится осваивать не особенности работы конкретной СУБД, а хитрости и фичи самой IDE), так и в их реализации (поэтому такие системы обычно закрытые и очень платные). Даже многими (включая меня) любимый DBeaver, флагман среди open sourse DB IDE, предоставляет поддержку NoSQL-решений (а какой проект сейчас обходится без них) только в своей Enterprise версии. В добавок ко всему этому сохраняется неиллюзорный риск того, что поддержку какой-либо очень нужной и интересной функциональности СУБД можно не дождаться в скором времени, пока разработчики IDE не посчитают нужным ее впилить (а могут вообще не посчитать и не впилить).

В ответ на сложившуюся ситуацию сами пользователи зачастую не дожидаются пока появится нужная фича или поддержка новой СУБД, а решают поступающие проблемы самостоятельно и наиболее подходящим для себя и своего проекта способом. GitHub просто кишит такими решениями разной степени сложности. В основном это наборы sql-скриптов на все случаи жизни (dataegret/pg-utils, NikolayS/postgres_dba, gwenshap/Oracle-DBA-Scripts, ktaranov/sqlserver-kit, lestatkim/opensql). Или консольные утилиты, такие, как top-подобные pg_activity и pgcenter. А также всевозможные web-based тулзы, начиная от вполне самостоятельных клиентов и средств мониторинга (pg_web, pg_hero) и заканчивая, например, просто html-обертками над системными таблицами (pg_web_stats, pg_stats_viewer). В результате чего складывается целый класс решений вида «programmers-for-programmers», «DBA-for-DBA», с помощью которых простые, и не очень, пользователи СУБД делятся своим опытом друг с другом непосредственно.

Похожая картина когда-то давным-давно наблюдались в области администрирования серверов и управления конфигурациями ПО. Тогда с постоянным появлением новых требований и технологий инфраструктура проектов стала заметно усложняться, резко увеличивалось количество серверов и софта, на нем работающего. А также появилась необходимость более частой, а затем и непрерывной поставки ПО с новыми бизнес-фичами заказчику. Существующие средства для конфигурирования и управления всем этим хозяйством плохо справлялись, в результате чего появился подход «Infrastructure as Code» и такие инструменты, как Ansible, Chef, Salt, Puppet и др., где конфигурирование инфраструктуры осуществляется на специальном DSL. Что даёт больше гибкости и свободы творчества. А код на таком DSL участвует в стандартном жизненном цикле наряду с основным кодом приложения (на Java, C#, Ruby или любом другом языке программирования), а именно — хранится в системе контроля версий (со всеми вытекающими — брэнчи, форки, code review), собирается в билды на сервере сборок, запускаются автоматические тесты и пр.

В дальнейшем влияние такого подхода стало заметно и в других областях:

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

Более подробную информацию на эту тему можно найти в докладе Александра Тарасова (aatarasoff) «Everything as a Code».

А что на этот счет в бескрайнем мире баз данных? Набрав в Google простое словосочетание «Database as code», я не нашел ничего интересного, кроме одного-единственного (но зато какого!) поста на DZone — «Database as Code: a Novel Concept».


Мы много говорим о database-first подходе. Мы много говорим о том, что данные — это самый ценный актив предприятия. Но как насчет концепции, представленной Dan North на третьем слайде его презентации? Что если относиться к базе данных как к коду?

Звучит заманчиво, а на слайдах #5 и #6 (к сожалению, видео я не нашел) описываются 2 подхода к управлению схемой БД «через код» — через инкрементальные миграции (Liquibase, Flyway) и идемпотентные DDL-скрипты (Redgate). Таким образом, схема — это тоже код, она находится под контролем VCS, собирается на билд-сервере, выполняются автоматические тесты и все такое.


Что нам необходимо, чтобы изменить наше мышление в области работы с базами данных? Мы должны прекратить относиться к нашей БД как к магическому артефакту или как к уникальному сценарию и взглянуть на нее под тем же углом, что мы смотрим на обычный код нашего приложения.

Снова мощно сказано, у меня аж слезы на глазах наворачиваются. К сожалению, и в докладе, и в самом посте, «как код» рассматриваются только изменения схемы БД (миграция схем БД):


Мы относимся к исходному коду нашего приложения как к сокровищу. И это абсолютно верно, код — это сердце любого приложения. Но не должны ли изменения базы данных также находиться под управлением системы контроля версий, быть автоматизированными, быть готовыми к релизу по первому требованию и подчиняться «DevOps-законам», как и основной код?

Но минуточку…

Большинство современных СУБД предоставляют свой язык запросов, с помощью которого мы можем не только получать и изменять хранящиеся в ней данные (т.н. DML) и оперировать их схемой (т.н. DDL), а вообще получить (не побоюсь этого слова) любую метаинформацию о текущей БД и ее состоянии (из системных таблиц и представлений) и выполнять практически любые операции над ней (запустить БД, остановить, перевести в read only, собрать статистику, управлять памятью и пр). И такой код тоже вполне себе подходит под концепцию, описанную в предыдущем параграфе.

А когда речь заходит о БД и языке запросов, то первым в голову приходит, конечно же, старый и добрый SQL. Но можем ли мы рассчитывать на него (а заодно и на реляционные БД, с которыми у большинства он плотно ассоциируется) сейчас и в ближайшем будущем, учитывая огромный рост спроса на NoSQL-решения?

Вы можете справедливо меня спросить — о каком вообще SQL я тут разговариваю в эпоху NoSQL и schemaless databases, когда »пыльные реляционки доживают свой век исключительно в кровавом легаси Ынтерпрайзе». Ранний Хабр (как лакмусовая бумажка трендов в мире технологий) тоже когда-то был наполнен негативом по отношению к SQL и реляционкам и предвещал их скорейшую гибель (в скобках указаны количество голосов, а через слеш — количество комментариев):

Однако примерно с 12-года настроение на Хабре заметно меняется:

При этом анти-sql’ные и антиреляционные настроения продолжают иметь место, но реакция сообщества на них уже совершенно другая:

Подтверждение этих настроений можно найти в недавних докладах Константина Осипова (kostja) «NewSQL: SQL никуда не уходит» и Андрея Николаенко «Нереляционный SQL». Возьму на себя ответственность привести краткое резюме из обоих выступлений:


  • »SQL в NoSQL» — SQL (как это не странно) довольно комфортно чувствует себя и в NoSQL-среде. Практически во всех NoSQL базах есть возможность использовать какой-либо sql-подобный query language, как, например, CQL в Cassandra и ScyllaDB, AQL в Aerospike и N1QL в Couchbase, а в некоторых и полноценный (или максимально приближенный к нему) ANSI SQL — как в Tarantool, ClickHouse и CrateDB.
  • »SQL в облаках» — Облачные гиганты предоставляют поддержку самых разных SQL-хранилищ: Amazon RDS, Amazon Aurora, Oracle Cloud, Google Cloud SQL, Microsoft SQL Azure, Alibaba Cloud ApsaraDB, Yandex Managed Databases.
  • »SQL в BigData» — SQL давно и плотно влился в инфраструктуру Hadoop. В далеком 2009 году появился Hive со своим HiveQL, а далее, год за годом, стали появляться решения, уже напрямую поддерживающие SQL — Impala (2011), Spark (2013), Kudu (2014), Presto (2015), Phoenix (2017).
  • »SQL в Поточниках» — SQL стал практически стандартом для потоковых обработчиков данных: Flink, Samza, Storm, Apex, а с недавних пор еще и Kafka.
  • »SQL в NewSQL» — Многие современные СУБД активно развиваются в сторону NewSQL, где совмещают в себе преимущества как NoSQL, так и классических реляционных решений, включая широкую поддержку SQL (CockroachDB, FoundationDB, MemSQL).


Нужно больше аргументов с картинками!

Дальше приведу еще немного аргументов, но если и так все понятно, то можно смело переходить к следующему параграфу.

История баз данных в «No-нотациях»:
p9y38f9qglzusht-lxpeek8hwdk.jpeg

Также в последнее время появляется много новых и модных СУБД, которые являются «надстройками» над известными и проверенными реляционными СУБД. Например Postgres-based (Timescale и ToroDB), MySQL-based (RadonDB) и даже на базе sqllite (которая всегда позиционировалась как простая и надежная embedded-база) появился rqlite — «легкое распределенное реляционное хранилище». Либо реализуют интерфейс какой-либо популярной базы (например, MySQL для InfiniDB и TiDB). Такой подход хорош тем, что при новой модели данных мы остаемся на той же привычной платформе, которую знаем как конфигурировать и администрировать.

Ну, а для совсем уж «безсхемных» ребят тоже есть попытки создать общий универсальный язык «а-ля SQL», как, например, Eclipse JNoSQL, а точнее — его подпроект JNoSQL Aphrodite.

Google, который и является одним из родоначальников NoSQL-движения, также делает все больше акцентов на SQL. Сначала это был Spanner, а теперь активно развивается BigQuery:
0acf059d688ee90b4f21418ee8f536c4.gif

SQL-интерфейсами обзаводятся не только хранилища и обработчики данных. Например, с помощью osquery (от самого Facebook) и fsql на языке SQL можно получить много всякой полезной информацию из любой ОС или выполнять различные операции с файловыми системами.

lmij5y7bfgvhwx-tmtqfki68txy.jpeg

В общем, SQL вполне комфортно себя чувствует в современных условиях, в том числе далеко за пределами реляционок. Практически с любым источником данных можно «поговорить» на SQL или SQL-like языке, получить нужную информацию о данных или метаданных хранилища и выполнять какие-либо операции (например, что-нибудь создать, удалить, запустить, остановить и пр.)

Здесь и далее (для удобства и с вашего разрешения) под «SQL» я буду подразумевать не только «тот самый» стандартный реляционный SQL, но и все его подвиды (в т.ч. далеко не реляционные), да и вообще любой встроенный в БД QL, с помощью которого можно сделать что-нибудь полезное.

А к тому, что в далеком 92-м году появился замечательный ANSI-стандарт, согласно которому любая реляционная СУБД обязана уметь описывать свою внутреннюю структуру в специальной схеме — Information schema. Т.о. с помощью стандартного языка запросов к служебным таблицам/представлениям можно получить метаданные любой БД — как в ней содержатся схемы, таблицы, индексы, колонки и пр. Но на самом деле одной схемой данных это не ограничивается, и таким же образом (пусть уже и за пределами стандарта) можно получить информацию о процессах, сессиях, планах выполнения запросов, дисковой подсистеме, утилизации памяти и еще много чего другого.

Несмотря на то, что этот стандарт появился почти четверть века назад и только для реляционных БД, почти все современные NoSQL и NewSQL базы тоже реализовывают что-то похожее. Например, в Cassandra есть сразу несколько системных схем (а точнее keyspace’ов — system, system_auth, system_schema, system_traces), доступ к которым можно получить с помощью уже упоминавшегося CQL. В ClickHouse есть специальная схема «system». Разработчики из CockroachDB вообще замахнулись на реализацию стандартной information_schema. И даже документный Mongo радует нас системными коллекциями.


При этом наблюдается постоянный рост количества и расширение таких системных представлений. Например, в Postgresql (как БД с одним из самых активных сообществ) помимо реализации самой information_schema, собственной схемы pg_catalog и pg_stat-представлений имеет несколько официальных расширений в виде преставлений pg_stat_statements и pg_buffercache. А также дополнительные сторонние представления, такие как pg_active_session_history, pg_store_plans и pg_stat_kcache.

Практически любому узлу соответствует какая-либо системная таблица, которая отображает его структуру и/или состояние. То есть о своем внутреннем устройстве и состоянии БД может рассказать сама посредством своего языка запросов. Помимо этого многие СУБД предоставляет возможность с помощью своего языка запросов не только получить полезные метаданные, но и выполнять служебные операции — что-нибудь остановить, запустить, очистить, собрать статистику и пр. Так в некоторых СУБД команду «ALTER» можно применить не только к таблицам или колонкам, но и к другим объектам, например, к сессии (»alter session set sql_trace = true»), датафайлам (»alter tablespace add datafile») или системе целиком (»alter system kill session»).

Знание этих таблиц и запросов поможет как в разработке и администрировании, так и в освоении очередной новой СУБД. Понятно, что в одних базах такие возможности весьма развиты, и «кодом» можно сделать практически все, а в других гораздо скромнее, но определенно имеет место тенденция того, что все больше разработчиков СУБД будут развивать такие возможности в своих продуктах, а мы сможем более эффективно их эксплуатировать.


Вместо выводов и резюме

К сожалению, SQL уже давно и прочно воспринимается многими как язык «низкого уровня», некий «байт-код» для БД. Который не принято, а в некоторых обществах даже глубоко неприлично «писать руками» и вообще каким-либо образом контактировать с ним. Мы уже давно привыкли, что многочисленные DB-тулзы и фреймворки сами генерируют и выполняют за нас »хитрые и сложные» SQL-запросы к системе, и за этим процессом остается только наблюдать. Но давайте выйдем из зоны комфорта теплых ламповых графических интерфейсов и кодогенераторов и посмотрим на наши СУБД с точки зрения обычного кода. Тем более, что все необходимое для этого у нас есть.

Теперь по делу. Пользователи любой СУБД имеют возможность описать практически все аспекты работы со своей БД в виде кода, на простом, понятном и привычном многим языке. Это может быть не обязательно ANSI SQL, а любой SQL-like диалект, либо вообще свой собственный встроенный QL или API, в зависимости от используемой БД. Чем это полезно?


  • Не привязываясь к какому-либо инструменту, можно получить любую информацию о БД в нужном виде, либо выполнить любую операцию над БД;
  • Т.к. это все-таки обычный код, то и относиться к нему нужно как к любому другому «настоящему» коду. А именно, он должен быть понятен, структурирован и отформатирован по принятому стандарту, а также участвовать во всех этапах стандартного жизненного цикла кода — быть под контролем VCS, подвергаться Code review, участвовать в CI/CD pipeline’ах и пр. (а не «валяться» где-нибудь в папке под названием «SQL-tricks»). Что повысит его качество и ценность в команде.

Интересно ваше мнение на этот счет, пишите в комментариях — будем обсуждать.


В следующем посте я планирую на конкретных примерах проиллюстрировать описанные выше идеи, а также расскажу о том, как мы в КРОК пробуем применить их в экспериментальном графическом DB-manager’е с открытым исходным кодом, который разрабатывается в рамках одного из исследовательских проектов.

© Habrahabr.ru