GitLab: с выходом версии 12.1 мы прекращаем поддержку MySQL

Автор оригинала: Kenny Johnston
  • Перевод


Сейчас мы расскажем, почему, начиная с версии 12.1, GitLab перестанет поддерживать MySQL.


В июле 2017 GitLab предупредил, что прекратит поддержку MySQL. Так вот, с выпуском 12.1 период подготовки к этому завершится, и больше мы MySQL поддерживать не будем. Решение непростое, и мы хотели бы поделиться доводами.


MySQL не очень подходил для нашего сценария использования


Есть немало удачных внедрений MySQL, однако в нашем случае он не совсем подходил. По сравнению с PostgreSQL MySQL имеет ряд ограничений, что приводило к проблемам с PostgreSQL при попытках приспособить MySQL. Вот небольшой список ограничений:



Он замедлял нас


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


Отдельно стоит упомянуть нашу систему CI, которая прогоняла тесты дважды, таким образом прекратив поддержку MySQL мы сократим время тестирования и расходы на инфраструктуру. Расходы, надо сказать, значительные, не окупаются малым числом пользователей на MySQL.


Мы теряли преимущества обеих серверных частей


Поддерживая обе серверные части (PostgreSQL и MySQL), мы не могли в полной мере воспользоваться ни одной из них. Там где хотелось бы использовать особенности производительности и надежности какой-либо из них, приходилось сводить все к наименьшему общему знаменателю. Пример (не единственный): мы хотели использовать LATERAL JOIN PostgreSQL для оптимизации событий на панели управления, но у нас не получилось потому, что мы использовали MySQL.


Почти все наши клиенты на PostgreSQL


Ориентируясь на данные Usage Ping, мы четко увидели, что подавляющее большинство клиентов уже перешли на PostgreSQL. Тренд достаточно устойчивый, к примеру в последнее время на 1200 установок с MySQL было порядка 110000 установок на PostgreSQL.


Мы уверены, что наши пользователи, которые применяют MySQL, могут достаточно просто сменить базу данных, переходя на PostgreSQL при обновлении до gitlab 12.1 и новее.


К слову, сами мы не работаем с MySQL, а это значит, что мы не сталкивались с проблемами ДО наших пользователей.


Нужна помощь с миграцией?


Если вы из числа таких пользователей, то для руководства по переходу с MySQL на PostgreSQL ознакомьтесь, пожалуйста, с документами по миграции.

Southbridge
419,53
Обеспечиваем стабильную работу серверов
Поделиться публикацией

Комментарии 191

    +9
    Сразу вспоминается:
    переход Uber с PostgreSQL на MySQL
      +3
      Разные условия — разные инструменты. Другое дело, что переход с Mysql на PostgreSQL у Uber-а был, мягко говоря, не сильно обдуманный. Тут уж надо выбирать — или шашечки (они же хайп), или ехать (здравый смысл при выборе софта и не только).
        +2

        Здесь параллельно поддерживались обе СУБД. Так что тут как такового перехода вообще не будет.

          –3
          Сразу вспоминается как Gitlab случайно удалил свою продакш-базу и положил весь сервис. Переход на psql от этого не спасет, так что пусть не торопятся)
          +14
          Это к вопросу, что БД это просто хранилище данных, нужно делать продукты так, что бы можно было использовать любую СУБД легким щелком переключаясь между ними.
          Этот аргумент часто всплывает, когда идет сравнение, где хранить логику приложения в БД или в коде.
            +31
            так, что бы можно было использовать любую СУБД легким щелком переключаясь между ними.

            Вот только это всегда идет ценой немалой потери производительности из-за невозможностии использовать специфичные для конкретной субд оптимизации
              0
              Вот только это всегда идет ценой немалой потери производительности из-за невозможностии использовать специфичные для конкретной субд оптимизации

              Как-то слишком категорично. Очень многие фреймворки и орм позволяют выбирать «драйверы» для конкретных бд (со специфичными оптимизациями под капотом), при этом не меняя сами абстракции с которыми вы работате в коде.
                +1
                Про закон дырявых абстракций слышали? В случае с СУБД — он особенно жёстко работает: чтобы ваша программа быстро работала вам нужно учитывать её особенности ещё на этапе создания схемы хранени данных. Никакие «драйверы» вам не помогут, если вы заложитесь на какую-то операцию, которая в одной СУБД делается быстро, с индексами, а в другой — только полным сканом всей базы.

                Пример вот прямо здесь же, в этой статье, обсуждался: PostgreSQL умеет искать по подстроке в текстовых полях с использованием индекса, а MySQL — нет, только прочёсывать всю базу. И что ваши «драйвера» могут с этим сделать?
                  +2

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

                +11
                БД это просто хранилище данных
                Но ведь БД уже давно не только хранилище данных. Если так считать, то можно и в текстовом файлике данные хранить :)
                  +5
                  Если так считать, то можно и в текстовом файлике данные хранить :)

                  Если что, то как раз недавно на конференции представитель одной очень большой компании, у которых самый настоящий HighLoad, сказал, что в некоторых подсистемах они так данные и хранят. И получается быстрее, чем в базе.


                  Каждому применению — свой инструмент. Очень часто мы зацикливаемся на одном («когда у тебя в руках молоток, то все вокруг — гвозди»).

                    +1
                    Да, мы тоже так делали. Без всяких SQL-запросов просто 2-3 if'а в коде, и перелопачивается инфа проще и быстрее :)
                      +4
                      А что начнется, когда потребуется конкурентный доступ…
                      А если захочется немного оптимизировать доступ и добавить индексный файл для поиска, управлять кэшированием.
                      ОЙ! Кажется мы пишем новую СУБД :)
                        +3

                        Требования всегда меняются. И очень часто меняются не те, которые мы ожидаем. Планировать изначально: «А здесь поставим то-то, потому что наверняка через год понадобится то, то, и то» часто оказывается ошибкой. Через год могут появиться совсем другие требования, или данную подсистему вообще придется выпилить, или она продолжит удовлетворять новым требованиям.


                        Предсказать может помочь лишь огромный опыт, или когда далеко не первый раз делаешь что-то типичное. В других случаях (да и с опытом тоже), очень часто предположения оказываются неверны.


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

                    +4
                    SQLite наше всё :)
                    +1
                    Знаете, вторая сторона правды в том, что запросы ORM всё равно приходится как-то оптимизировать в случае более-менее приличной нагрузки, а железом и деньгами можно залить далеко не всё.
                      +31
                      железом и деньгами можно залить далеко не всё.

                      Вы даже не представляете сколько таки можно и таки заливается железом и деньгами.
                      Я видел такие чудеса! Там где можно написать просто и красиво и использовать один простенький сервак и монолитное приложение легко справится. Люди ставят несколько кластеров раскидывают десяток криво написанных и несбалансированных микросервисов без какого-либо вменяемого мониторинга и без тестирования (никакого! ни юнит ни интнграционных, ни нагрузочных). Сверху ставятся рэндомно настроенные системы кэширования и CDN. И потом активно сосутся деньги на борьбу с «большой нагрузкой». Поверьте, деньгами можно залить все, особенно собственную некомпетентность. Как вы сможете объяснить некомпетентному авторитарному руководителю отдела с такими же как он некомпетентными админами и девелоперами, что вся их работа просто результат их же некомпетентности? они все получают зарплаты и премии, а язык технических аргументов не понимают и не собираются разбираться что и как можно улучшить. Им это не нужно — им проще и понятнее запросить бюджет на пару десятков новых серверов и нанять еще десяток людей чтобы все это «поддерживать».

                      Извините, к ORM мой коммент вообще не имеет отношения, ни в ту ни у другую сторону, просто немного наболело. Просто поверьте деньгами заливается порой так много, что волосы встают дыбом и теряется дар речи.
                        0
                        Да я вас понимаю, что вы. Просто конкретно сегодня серебряной пулей объявлен ORM (ну, судя по тому, что крутится вокруг моих знакомых), а так — картина как раз именно такая. Только это… «Лить деньги» и «Залить деньгами» это немного разные критерии, на мой взгляд. Вот вы как раз описываете историю про «лить деньги», а «залить» — это забыть на 3/5/7 (ну, если сильно повезло) лет. И вот этого как раз и не происходит.
                          +2
                          «Лить деньги» и «Залить деньгами» это немного разные критерии, на мой взгляд

                          Поддержу. Алгоритмическую сложность не зальёшь. Я лично видел O(nˆ3), где можно обойтись O(n*log(n)). И в таких случаях никакой кластер-хуястер не поможет xD
                          Ну, точнее поможет на пару месяцев, пока нагрузка низкая и медленно растёт.

                            +3
                            во во, я видел как одна фирма реализовала простейший алгоритм вида: изображение с камеры минус фон и если слишком много пикселей больше некоторого порога то останавливаем станок (оператор руку в область плазменой резки засунул) на кластере из серверов каждому отдавалась свой кусочек изображения 50 мегапиксельного), но моя реализация управилась в реалтайме на микроконтроллере. Они его реализовали не простым сравнением кадров с ресайзом кадра хотябы до 1 мегаписеля (хотя ноготь занимает около 5% экрана, ладонь половину, да и область резки 20х20см, и зачем туда 50 мегаписелей и камера за миллионы рублей?), нет они вычисляли оптический поток новомодным кодеком AV-1 всех 50 мегапикселей с макс качеством, с максимальными настройками предикторов движений и граней и тд. Всё равно им не удавалось залить это деньгами, серверными шкафами и превзнемоганиями — оно попросту глючило (на краях разрезки) и было неотзывчиво что жесть (пинг до минуты).
                            +1

                            Кем он объявлен? У вас устаревшая информация: актуальная серебрянная пуля — CQRS+ES :)

                              0
                              уже не актуально. теперь serverless в тренде :)
                        +13
                        нужно делать продукты так, что бы можно было использовать любую СУБД легким щелком переключаясь между ними

                        Пишу я проект на пострге… и в постргре есть функционал, который позволяет мне ускорить запрос в два раза, но этого функционала нет в других субд или в какой то конкретной субд. Получается, из ваших слов, я не должен его использовать потому что «потом» если я вдруг захочу заменить его на что то другое щелчком пальца, у меня возникнут проблемы?
                          0
                          Вы можете использовать любой функционал, но там где он недоступен его просто не будет.
                          Вот вам пример рабочего кода: github.com/TYPO3/TYPO3.CMS/blob/master/typo3/sysext/core/Classes/Database/Query/Expression/ExpressionBuilder.php#L296

                          Обратите внимание на oci8, pdo_oracle кейс.
                            0
                            Извините, я не понял, что вы хотите до меня донести. Как этот класс решит озвученную мной проблему?
                              0
                              Класс лишь пример. Вообще я указывал не на весь класс, а на функцию реализующую FIND_IN_SET в различных базах данных. И в ней видно что oci8, pdo_oracle бросает exception, предупреждая что данный оператор не поддерживается.
                              Вот я и хочу донести, если выпишите универсальную систему, вы можете использовать функционал
                              который позволяет мне ускорить запрос в два раза
                              но там где это не поддерживается вы его просто не используете.

                              Отвечая на ваш вопрос: вы можете использовать любой функционал, но система должна быть отказоустойчивой в случае отсутствия данного функционала. В вашем случае: если база не пострге, не используем функции ускорения запросов.
                                +5
                                Система не обязана быть отказоустойчивой при смене бд. Если я изначально для себя решил, что мне нужен просто сайт на постргре и я не планирую переезд на другую платформу — это мое право.
                                Не говоря о том, что кинутые в последствии эксепшены при смене базы, это не решение самой проблемы. Мое личное мнение, что проще писать все на чистом постргре и затем если когда то это понадобится один раз сесть и переписать все узкие места, чем поддерживать все это.
                                  +2
                                  Вы сами себе противоречите «я не планирую переезд на другую платформу» хотя изначально было «если я вдруг захочу заменить его на что то другое щелчком пальца».

                                  В целом и автор, комментарием что вы процитировали, прав и вы. У него мыльтиплатформенная система, он учитывает её особенности. У вас она завязана на конкретную базу, вы учитываете только её особенности.

                                  Поэтому если, как вы написали в первом посте, вы хотите изменить базу щелчком пальца, то вы должны сразу писать что-то мультиплатформенное. Если, как вы написали потом, вам нужен сайт на постргре, то уже как вам удобно.
                                    0
                                    Хорошо, понял вас, согласен. Надеюсь мне не придется поддерживать такую систему))
                                      0
                                      Если честно, мне вообще сложно придумать ситуацию, когда может понадобиться писать проект под несколько бд с возможностью быстрого переключения между ними))
                                      Разве что если вы делаете какой то продукт для клиентов, что бы они могли сами выбрать бд.
                                        0
                                        Вы опять противоречите себе, причём в этот раз в пределах одного комментария!
                                        мне вообще сложно придумать ситуацию, когда может понадобиться писать проект под несколько бд
                                        вы делаете какой то продукт для клиентов, что бы они могли сами выбрать бд.
                                          0
                                          Почему противоречу, мне пришлось напрячься что бы его придумать…
                                            +2
                                            symfony.com
                                            www.yiiframework.com
                                            www.drupal.org
                                            ru.wordpress.org
                                            typo3.org

                                            Разработчики перечисленных и многих подобных проектов сейчас поперхнулись своими напитками.

                                            PS Пора расширять свой кругозор)
                                              –7
                                              расширяйте, я не против)
                                                +1
                                                А зачем всех этих перечислять, если, собственно, вся статья о компании, выпускающей «какой то продукт для клиентов, что бы они могли сами выбрать бд»?
                                                  0
                                                  Перечислил первых кто пришёл в голову.
                                            0
                                            Учавствовал в разработке проекта под 4 СУБД — Oracle, IBM Informix, PostgreSQL, MS SQL Server. Заказчик еще запускал систему на MySQL, хотя мы предупреждали, что с ним она не тестировалась. Т. к. писалось все на Java, мы просто использовали Hibernate и HQL для запросов, без использования фич конкретных СУБД.
                                              0

                                              Аналогично, использовали исключительно ORM, исправили немного именование индексов, и система заработала на второй СУБД. Попробовали после этого на третьей — завелась без вопросов.


                                              И да, я принципиально стараюсь не выходить за ORM даже при работе с одной СУБД: так значительно проще поддерживать код длительное время с плагином IDE под ORM: статический анализ работает даже в запросах и находить/рефакторить значительно проще.

                                    0
                                    Справедливости ради, это цена за универсальность. В oracle подобное реализовать возможно процедурой.
                                    –5

                                    На мой взгляд, так не бывает. Если у вас есть возможность на ровном месте уменьшить время отклика в 2 раза, то или у вас где-то в цикле стоит sleep, или вы получаете рост производительности по одним параметрам за счет просадки производительности по другим параметрам. Грубо говоря, уменьшили время работы запроса — потратили оперативную память.


                                    Если произвести анализ, за счет чего происходит улучшение, то, как правило, можно обнаружить, что в большинстве топовых продуктов такая оптимизация уже есть, только устроена немного по-другому, или можно самому ее реализовать.

                                      +7
                                      Это только на ваш взгляд так не бывает. Наверное, вы не работали с планами запросов и не пробовали использовать хинты/менять запрос для изменения этого плана. Или вообще не представляете как работает запрос, что некоторые СУБД кэшируют план и т.д. Самый банальный пример с алгоритмами соединения таблиц, когда планировщик выбирает, например, Nested Loops вместо Hash или Merge Join
                                        –1

                                        И что же такое есть в одной СУБД, чего нет в другой?

                                          +4
                                          1) Например, хинты. Насколько я помню, в Postgre их не завозят, в Oracle они в комментах, в MS SQL они часть синтаксиса.
                                          2) В Postgre табличные выражения, насколько помню, указывают планировщику указывают на то, что эту часть нужно материализовать во время выполнения запроса (или как-то так, я с Postgre не работал). А в Oracle и MS SQL они не влияют на план запроса.
                                          3) MySQL вроде как не поддерживает оператор MERGE из стандарта SQL 2008 года. Есть аналоги, но не полностью покрывают функционал.
                                          4) MySQL не поддерживает транзакционность DDL-операций. Из-за этого сложности с накатом миграций.

                                          Продолжать можно до бесконечности
                                            –4

                                            Это все про удобство. Ничего из этого выигрыша времени выполнения запроса в 2 раза не дает.


                                            MS: Because the SQL Server query optimizer typically selects the best execution plan for a query, we recommend only using hints as a last resort for experienced developers and database administrators.


                                            Oracle: test by means of hints, but use other techniques to manage the SQL execution plans, such as SQL Tuning advisor and SQL Plan Baselines.

                                              0
                                              Ключевое слово здесь «typically». А неправильно выбранный план даст просадку не в два раза, а в сто.
                                                –2

                                                Так не пользуйтесь хинтами и не будет у вас просадки в 100 раз. Именно про это же и пишут производители.

                                                  +8
                                                  У вас слишком упрощённое восприятие предметной области. План может сломаться из-за кучи различных факторов: неправильная статистика, сильная фрагментация индекса, сам индекс был оптимальным, а может стать неоптимальным. И в каждом из этих случаев тупо положившись на оптимизатор легко получить деградацию на порядки. И простого решения уровня «не используйте хинты» здесь нет.
                                                  И, разумеется, хинты — это не про «про удобство». Это про боль, страдания, ненависть. Но никак не про удобство.
                                                    0

                                                    У вас есть примеры, когда запрос без хинта работал нормально, а потом резко деградировал на порядки, причем, если бы в нем был хинт, то деградации бы не произошло?

                                                      +3
                                                      Разумеется. Вы, вероятно, просто не работали с большими базами данных)
                                                        0

                                                        Смотря, что считать большими. Те базы, с которыми я работал, я большими не считаю.

                                                        +2
                                                        Разумеется. Чуть ли ни штатная ситуация даже со небольшими данными, порядка лишь миллионов записей, когда оптимизатор не справляется с оценкой мощности подветвей запросов даже средней (с виду) сложности.
                                                          +1
                                                          Вот вам наглядный пример из моей практики:
                                                          Приложение посылает к базе MS SQL несколько раз запрос, в котором в области WHERE идет фильтрация в каждом отдельном случае по разному значению идентификатора. В запросе накручено много всего (его генерирует ORM). Но, обычно, он выполняется быстро (в зависимости от кол-ва возвращаемых строк — от 0 до двух минут). И тут иногда случаются дикие просадки, запрос висит по часу.

                                                          Пошел разбираться — вначале к серверу приходили запросы по идентификатору, по которому одна-две записи. SQL Server генерировал план запроса с использованием Nested Loops для джойнов. И кэшировал этот план. А потом к нему приходил запрос, по которому данных в несколько тысяч раз больше. Но план брался из кэша — не оптимальный.

                                                          Это лечится, например, хинтами. Тут два варианта, либо явно указывать алгоритм соединения таблиц в проблемном месте. Либо указывать запросу, чтоб он строил план без учета закэшированного. Так как я работал через ORM то я просто упростил запрос, но в ином случае, возможно, использовал бы хинт.
                                                            0
                                                            T-SQL, разбор xml на сервере.
                                                            С хинтом и без хинта время разбора большой ( пара сотен мб ) xml отличается на 2 порядка, пока шли небольшие xml — проблема не была видна.
                                                            на всякий случай, хинт:
                                                            OPTION ( OPTIMIZE FOR ( xml = NULL ))
                                                              –2
                                                              Как раз время разбора xml ни от какого хинта зависеть не может. Не там тормоза ищете.
                                                                0

                                                                Не "время разбора", а план запроса, и общее время этого самого запроса. Наверняка же та же самая проблема что и в комментарии выше: кешируется план, составленный для xml из пары записей, а потом прилетает xml из пары миллионов записей и все.

                                                                  +2
                                                                  Это уже теплее, но у автора коммента, на который я отвечал (вы же прочли?), подозрение конкретно на время разбора xml, и отвечал я именно на это. Ну и сравните:
                                                                  Не там тормоза ищете
                                                                  Не «время разбора», а план запроса
                                                                    0
                                                                    Да, возможно кривой план.
                                                                    Но с хинтом и без скорость работы процедуры различается на 2 порядка.
                                                                      0
                                                                      Так для этого и нужно читать оценочные мощности ветвей в плане: для пустого xml (при optimize for(xml=null)) оптимизатор предполагает пустой результат разбора, но поскольку нулевые оценочные мощности он никогда не ставит — оценочная мощность этой подветви будет равна одной строке. Соответственно, может меняться и остальной план из этой оценки, вот и вся магия.
                                                    0
                                                    > MySQL не поддерживает транзакционность DDL-операций. Из-за этого сложности с накатом миграций.

                                                    В восьмёрке вроде как чинят.
                                                    dev.mysql.com/doc/refman/8.0/en/atomic-ddl.html
                                                +1
                                                так не бывает

                                                Да легко: в моём случае пересадка на постгрес с переписыванием кучи запросов (много insert into select… group by, insert on duplicate key) в эквивалентные дала ускорение в три раза (с полутора минут до 30 секунд). Памяти постгрес жрал «стандартные» 12 метров на всё про всё.
                                                Да, какие-то запросы в постгресе выполняются медленнее (например, вставка в таблицы с большими первичными ключами ака наивные счётчики просмотров или запросы содержащие not in), но мне из постгреса с настройками «для калькулятора» в среднем удаётся выжать намного больше, чем из мускуля который когда-то долго настраивали под железо.
                                                  +1

                                                  В старших редакциях MS SQL Server можно создавать материализованные (индексированные) представления, и они будут автоматически подхватываться для некоторых запросов, выступая как что-то вроде индекса.


                                                  А в младших редакциях того же самого MS SQL Server, вроде SQL Server Express, такой возможности нет. Более того, даже прямая выборка из материализованного представления не использует это самое представление, если забыть указать ему with(noexpand)!


                                                  Вот тут-то и выходит, что на каком-нибудь простейшем select count_big(*) from foo where bar = 'baz' разница в производительности будет хоть в 1000 раз, хоть в 10000 — в зависимости от того, чему это count_big(*) равно.


                                                  И получается выбор: либо писать запросы строго для enterprise-редакции, либо писать более сложные запросы для любых редакций sql server — либо денормализовывать схему БД просто из-за того, что в природе существует MySQL, где аналогичной функциональности нету.

                                                    0
                                                    Ещё веселее, когда нужно реализовать одинаковый функционал на 2000, 2008 и 2016 SQL Server — потому что они есть у заказчиков и менять никто ничего не будет.
                                                    Смотришь, в какие граблевилосипеды разворачивается быстрый код и структура БД при переходе с MSSQL 2016 на 2000 и становится грустно.
                                                      0
                                                      Незнаю как в MSSQL но в Oracle и PostgreSQL materialized view, это вьюшка со своим стораджем, что позволяет, например, строить сложные индексы по нескольким полям разных таблиц
                                                        0

                                                        Так и есть...

                                                    0
                                                    Для таких случаев придумали стратегии: если мы на постгресе, то используем оптимизированный запрос, если нет — делаем медленно.
                                                    0
                                                    Именно это говорит дядюшка Боб в Чистой Архитектуре. Мол, архитектуру надо делать такую, чтобы вопрос о выборе конкретной технологии можно было откладывать как можно дольше.
                                                      +3
                                                      В большом серьезном проекте это вряд ли получится, иначе придется изначально завязываться на то что одни и те же данные могут храниться в десятков разных типов баз данных (key-value, sql, bigdata, текстовые файлы, mongodb) и интегрироваться десятком разных способов (rest, soap, css архивы, message broker и т.д.). Это ограничит возможный функционал базы данных и интеграции (то есть никаких сложных sql запросов или аутинтификации от soup) и сильно усложнит приложение.

                                                      Скорее нужно как можно раньше ограничить какие технологии могут быть потенциально использованы в будущем в вашем проекте, а какие нет (в смысле, понять что забивать гвозди микроскопом вы никогда точно не будете).
                                                      Если вы делаете простой микросервис, который просто сохранает и возвращает данные из sql базы, то при изменении требований с sql базы на mongoDB и интеграции с rest на soup намного проще выкинуть старый сервис и написать новый микросервис с нуля, чем пытаться изначально сделать максимально универсальную архитектуру.
                                                        0

                                                        Он предлагает абстрагировать бизнес-логику от систем хранения, это да. Но почему мало кто замечает, что он в этой книге постоянно упирает на экономику процесса и связанную с этим разумную достаточность?


                                                        Здесь же явно проблемы не с абстракциями, а с экономикой. Существенное сокращение затрат для продуктовой компании вполне может окупить отвал не критичного количества принципиальных пользователей именно mysql. Абстракции сами по себе стоят денег, чего уж говорить о конкретных реализациях!


                                                        Да и "универсальный" код (это если не делать отдельных реализаций), зачастую, сильно связывает руки. Знаете, я был счастлив, когда в январе узнал, что мне не надо больше оглядываться на ms sql 2000. А ведь у меня не было под него отдельной реализации какой-нибудь абстракции, только необходимость избегать использования нескольких полезных возможностей.


                                                        Так что пусть себе отказываются. Поддерживаю. О себе тоже иногда надо заботиться.

                                                        +7
                                                        Отвечаю сам себе. Поскольку раз в час у меня комментарий. Впрочем еще один минус в карму и будет раз в сутки, что означает в реальности, что писать я вообще перестану.
                                                        Так случилось, что я всегда работал в «кровавом энтерпрайзе» в различных областях. Где из БД пытаемся выжать все. Из конкретной СУБД.
                                                        Конечно периодически идут рассмотрения перехода на другую СУБД. Это всего выходит очень дорого с неопределенным результатом.
                                                        Поэтому мне удивительно слышать такие речи, что СУБД не важна и можно легко писать так, что можно переключаться между СУБД быстро. Используя всякие ORM.
                                                        На мой взгляд это возможно в проектах с очень примитивной структурой БД и очень примитивной логикой работы с данными.
                                                        Пример данной статьи говорит о том же.
                                                        На это мне и хотелось обратить внимание.
                                                        P/S: Да, моя ирония не прокатила, пришлось писать объяснение более подробно.
                                                          +2
                                                          Ахаха, вы бы комментарии аккуратнее писали. Вас понял как раз в противоположном смысле.
                                                            +4

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

                                                              0

                                                              В Энтерпрайзе много данных. Очень много. И они часто лежат в самых разных местах: какие-то попадают на внешний ftp, какие то лежат в другой бд, третьи — это действия пользователей в ERP системах. И для сборщиков всего этого пишется много etl'ов. Затем имея все это в бд, тебе надо это все пересчитывать, используя наверное хранимые процедуры. Посчитанные данные надо показать пользователю, например через power bi, который очень любит базу ms sql. И я уже молчу про тонну триггеров, которые аналитики вешают на таблицы. И я замечу, что все это может делать аналитик, который просто хорошо знает SQL.
                                                              И вот как все это переключать на другую БД щелчком пальцев, и самое главное Зачем? Вопрос открытый.

                                                                0
                                                                каким образом логика работы с данными может быть зависеть от системы хранения.

                                                                Логика не зависит, зато зависит реализация этой логики. Это тоже самое сказать, что логика работы с данными не зависит от языка программирования.
                                                                Могу привести свой пример из почти «кровавого энтерпрайза»
                                                                Есть ERP-система, в которой невозможно изменить логику в абсолютно любом месте. Например, расчет каких-то значений, или контроль ввода данных, или пересчет значений в других таблицах. И единственный выход в данной ситуации писать бизнес-логику на триггерах в SQL-таблице.
                                                                Совсем стандартный случай, когда в самих триггерах фиксируется кто и когда отредактировал запись в БД, тк клиентский не протоколирует изменения.
                                                                Штатного функционала в ERP-системе на программирование логики на этапах before-insert, after-insert нету и не предвидится. В тех местах, где она доступна, пишется на таком псевдо-языке, что хочется убиться об стену. sad but true.
                                                                В другой ERP-системе видел примеры, когда XML-сообщения парсились функциями из SQL, тк в самой системе для работы с XML почти ничего нет.
                                                                Еще пример, например, есть расписание сотрудника с обедами и техническими перерывами, со сменами в разное время, и вот это вот все. Вся информация раскидана по разным таблицам, типовые дни в одном месте, перерывы в другом, праздники в третьем, и тд. И как всегда, неожиданно, нужно сгенерить некий табель рабочего времени сотрудников.
                                                                Есть несколько вариантов решения этой, казалось бы, стандартной задачи. Обратиться к разработчику этой ЕРП-системы, ответ: функционал будет в следующей версии, когда-нибудь. В течение семи лет разработчик так и не сделал этот функционал.
                                                                Второй вариант, написать на SQL хранимую процедуру, которая по некоему алгоритму обойдет все эти таблицы, и запишет результат в некоторую временную таблицу. Сделать простой select к произвольной таблице и выдать пользователю ERP-система умеет.
                                                                  0

                                                                  Так тут дело в том, что код ERP менять нельзя, а не в том, что база лучше.

                                                                  +1
                                                                  В банковской системе, с которой я работал было порядка 6 000 таблиц и около 10 000 хранимых процедур (MS SQL). Собственная самописная информационная банковская система ИБС (банк просто купил поставщика ИБС и поставщик стал внутренним ИТ подразделением банка). Структура данных была не примитивной. Реализована собственная система логического управления документами и движением документов с учетом маршрута и статуса. Систему создавали очень грамотные люди, мне было чему поучится. Объем данных порядка 2 Tb, на момент когда я там работал.
                                                                  Другая область это сеть магазинов (что то около 1500 магазинов в различных городах). Схема работы с данными аналогична. Данные с касс грузятся в БД, проходят при этом различные преобразования и агрегации, собираются в одно место, где потом раздергиваются на отчеты и пересчета различные. На основе наличия товара на складах и остатков в магазинах по хитрым алгоритмам создается распределения товара по магазинам и на склады падают задания на комплектацию. Общий объем данных поменьше, порядка 1.5 Тб, но быстро растет. Тут исторически разбито на десяток БД, не всегда логично и на несколько серверов (физических).
                                                                  Или система курьерско-складского оператороа, распределенного по порядка 60 филиалов по стране. У этого бегает репликация между локальными филиалами и центральным офисом.
                                                                  Тоже накручено всяких разных правил и логики, от приема заказов, до распределения курьеров и складской логистики и отслеживания груза по пути следования.
                                                                  Споры, которые я упомянул выше, касались в каком месте располагать обработку логики работы приложения (всякие простые валидации полей при вводе оператором, это тоже примитив, это все может быть на уровне приложения, хотя при этом порой могут ходить запросы в БД) в приложении каким то образом (возможно в некотором слое какой нибудь трехзвенки, не знаю, мне с такими системами не приходилось работать) или с помощью хранимых процедур в СУБД. Мое мнение в процедурах БД удобнее, поскольку СУБД и заточена под обработку данных и лепить для этого еще какой то слой, излишнее усложнение архитектуры.
                                                                  Аргумент за обработку логики в приложении где то, который мне было нечем крыть, это свободный выбор СУБД для работы, типа переход по одному щелчку мышки к другой СУБД. Вот серьезных систем уровня описанного мной выше, которые могут легко перепрыгивать из одной СУБД в другую я не встречал.
                                                                  И статья, под которой мы тут комментируем, так же показывает, что не так все просто.
                                                                  Что касается настройки запросов и хинтов, которые упоминают в комментариях.
                                                                  Когда запросы тривиальны (как я это называю) решения тоже тривиальны: повесить там индекс и радоваться.
                                                                  Но вот когда запросы сложные идут с различными джойнами и всякими разными штуками, которые до тебя уже тюнинговали грамотные люди, тогда сложно.
                                                                  Где то временные таблицы помогают, где то CTE и оконные функции (вот еще пример. Оконные функции в MS SQL мы широко используем, а в других СУБД это реализовано по другому. А без них порой все колом встает и выполняется неприемлемое время или валит загрузку по процессору).
                                                                  Недавно забавный эпизод был. Когда удаление индекса ускорило на 2 порядка выполнение запроса. Хотя вроде бы простая ситуация.
                                                                  Т.е. понятно, что какие то методы оптимизации нарабатываются, но часто идешь просто перебором. Пробуешь различные штуки, которые когда то применялись успешно, пока не попадешь на то, что тебе помогает. Какой то серебряной пули как то не видно (опять же кроме тривиальных случаев). Навесили индекс, другой, третий… после n-ного запись в таблицу начинает плакать.
                                                                  А как оттюнингованную такую БД переводить на другую СУБД легко, не знаю. Это требует времени и денег, а в это время бизнес бежит вперед и идут потоком доработки.
                                                                  P\S Спасибо всем, кто подкинул мне плюсов в карму. Пока пишу дальше.
                                                                    +1
                                                                    в каком месте располагать обработку логики работы приложения
                                                                    Мое мнение в процедурах БД удобнее, поскольку СУБД и заточена под обработку данных

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

                                                                      0
                                                                      Но ведь логика работает с данными.
                                                                        0
                                                                        Как правило логика основывается на данных и в результате происходит обработка данных.
                                                                        Конечно, если приложение управляет неким механизмом, тут ситуация другая может быть.
                                                                        Обработка изображений, да много чего в СУБД делать не будешь.
                                                                        Но если речь идет о работе с данными (а бизнес приложения это работа с данными), то и обрабатывать данные удобно в процедурах СУБД (если СУБД вообще позволяет хранимые процедуры).
                                                                        А так, взять млн. другой записей, пересчитать и сохранить результат расчета, зачем для этого данные тащить куда то в приложение, что бы там обработать, а потом снова отправлять в СУБД, если СУБД отлично с этим справится? Передал в процедуру параметры, она тут же взяла нужные данные, обработала и вернула тебе результат. Все просто и лаконично, без каких либо промежуточных слоев.
                                                                        Впрочем это мое мнение и мой опыт работы в различных отраслях. Каждому свое.
                                                                        Кстати, интересен был бы практический пример, какая логика описывается языком программирования в приложении?
                                                                          +1

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

                                                                            0
                                                                            Собственно все вами перечисленные фишки и были реализованы в нашей банковской системе (графического интерфейса графа движения документа не было).
                                                                            Все правила заданы были в процедурах SQL, к которым обращались интерфейсы. В конечном итоге все вами перечисленное основывается на данных, которые хранятся в БД. И при обработке логики в приложении приложение посылает запросы в БД.
                                                                            А есть еще групповые обработки пакетов документов. И по клику и по расписанию.
                                                                            Код процедур в контроле версий.
                                                                            Контроль доступа в соответствии с ролями обеспечивается силами СУБД + логика прав при определенном статусе документа.
                                                                            Все отслеживается, работа как с обычным кодом.
                                                                              –1

                                                                              Понятно, что можно реализовать на хранимках (хотя в разных SQL будет разная боль). Но вот что работа столь же удобна как с обычным кодом просто не верю. Одно версионирование кода процедур ни разу не встречал нормальной рализации, с историей, с ветвлением, со слиянием ветвей и т. п. Плюс в тех SQL с которыми плотно работал не было средств нормальной группировки хранимок, по сути они все разделяют одно пространство имён.

                                                                                0
                                                                                Одно версионирование кода процедур ни разу не встречал нормальной рализации, с историей, с ветвлением, со слиянием ветвей и т. п. Плюс в тех SQL с которыми плотно работал не было средств нормальной группировки хранимок, по сути они все разделяют одно пространство имён.

                                                                                Тут уже сказываются привычки. Т.е. тема «мне удобнее».
                                                                                Версионирование процедур делается так же как и любого другого кода. Текст процедуры сохраняется в файл. Процедура для работы в редакторе открывается не из БД SQL сервера, а из файла. Далее работа в контроле версий с файлом, как везде собственно, никаких отличий.
                                                                                Группировать хранимки можно префиксами, можно заводить при желании для каждой группы свою схему (в MS SQL), можно каждую группу хранимок складывать в свою БД, например, только это не нужно. Это снова попытка натянуть привычные сложившиеся методы из других областей. Т.е. снова вопрос привычки, взгляд из своей зоны комфорта.
                                                                                  –1

                                                                                  Текст процедуры или команда типа CREATE PROCEDURE? Или кто-то из SQL начился синкать своё хранилище процедур с ФС на клиенте?


                                                                                  Группировать хранимки можно префиксами

                                                                                  Вот сразу вспомнилась молодость, C и PHP 3. Не согласен, что всего лишь вопрос привычки, это вопрос удобства.

                                                                                    0
                                                                                    «Синкать» это синхронизировать?
                                                                                    Текст процедуры или команда типа CREATE PROCEDURE?

                                                                                    Занятно, такое разделение текста процедуры и команды на создание редактирование впервые от вас слышу. Обычно просто «процедура».
                                                                                    Первое сохранение может быть CREATE, далее ALTER.
                                                                                    Еще может быть при развертывании сначала проверка на существование процедуры, если ее нет CREATE пустышки, далее ALTER.
                                                                                    Так можно всегда использовать при сохранении файла с процедурой ALTER.
                                                                                    Можете назвать текстом, можете командой, можете скриптом.
                                                                                    Развертывание процедур, это отдельный вопрос.
                                                                                    Так же как и любое развертывание нового кода.
                                                                                    Может быть с изменением структуры БД, может быть без изменений. Это уже тоже организационные вопросы. Как построите.
                                                                                    Откат на предыдущую версию тоже отдельный организационный вопрос. Где то обязательно создание скриптов для отката, где то не парятся с этим. По разному.
                                                                                    Сейчас мы работаем прямо на боевом сервере, даже не фигак-фигак и в продакш, а сразу в рабочей БД, начинаю забывать всякие строгие правила, которые были при работе в банке :)
                                                                                    Сначала шокировало, потом привык.
                                                                                    Да, вопрос удобства, часто бывает вопросом привычки. Привык к окружению, сидишь в зоне комфорта, зачем вылезать, если жизнь не заставляет? :)
                                                                                      –1
                                                                                      Первое сохранение может быть CREATE, далее ALTER.

                                                                                      То есть по отдельному файлу на каждую версию процедуры, типа миграций схемы?


                                                                                      Еще может быть при развертывании сначала проверка на существование процедуры, если ее нет CREATE пустышки, далее ALTER.

                                                                                      Я не про развёртывание, а про разработку с локальной БД. Пришёл на работу, открыл IDE, изменил файл, сохранил и могу эту процедуру вызвать. Скрипты развёртывания или проверка существования мне не нужны в окне редактирования кода.


                                                                                      И откатывание на предыдущую версию лишь частный случай переключения между версиями.


                                                                                      Сейчас мы работаем прямо на боевом сервере

                                                                                      А как синхронизируете работу? Одному нужно пару строк в процедуру добавить вначале, другому в конец.

                                                                                        0
                                                                                        Вы меня несколько в тупик поставили.
                                                                                        Как работают программисты с файлами и контролем версий?
                                                                                        Открыл файл, изменил файл, сохранил файл. Закоммитил версию. При работе с процедурой все то же самое.
                                                                                        Для MS SQL открыли файл с текстом процедуры в мендежмент студии. Изменили, по F5 накатили ALTER на сервер свой локальный, проверили работоспособность, сохранили файл. В контроле версий закоммитили изменения.
                                                                                        Все.
                                                                                        Нужна предыдущая версия, перешли на ветку в контроле версий, открыли эту версию, работаете.
                                                                                        В чем сложность, что вас смущает?
                                                                                        Не забыть после открытия в студии F5 нажать, что бы версия на сервере синхронизировалась?
                                                                                        Развертывание, отдельный вопрос, как вы и сказали.
                                                                                        Сейчас мы работаем прямо на боевом сервере
                                                                                        А как синхронизируете работу? Одному нужно пару строк в процедуру добавить вначале, другому в конец.

                                                                                        Сразу скажу, я работаю в таком режиме 1.5 года и мне до сих пор это не нравится.
                                                                                        Просто команда маленькая и крайне редко нужно редактировать одну и ту же процедуру одновременно.
                                                                                        А так, в банке, где было 10-15 человек программистов, разруливается так же как и везде. У каждого (вернее было у группы, но при желании можно и каждому) своя БД для разработки, в ней работает.
                                                                                        Сливаются версии файлов в контроле версий, как и любой другой код, далее развертывается общая версия или в порядке очередности, это уже от проектов зависит.
                                                                                        На основная суть: процедура это код в виде текстового файла и работают с ней точно так же как и с любым другим кодом в виде текстового файла.
                                                                                          0

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


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


                                                                                          Вот и все, теперь таблица, поле, триггер и хранимка могут быть залиты на сервер строго в некотором порядке, иначе скрипты поломаются. Хорошо еще если не придется заливать разные версии одной и той же хранимки для выполнения разных миграций. И, что самое противное, успешное выполнение скриптов на тестовом сервере уже не означает, что они потом не поломаются на продуктиве. То есть деплой на прод больше не нажатие одной кнопки, а пара часов ручной работы в лучшем случае...

                                                                                            0
                                                                                            Когда вы делаете изменение структуры БД (добавление поля), вам в любом случае нужно синхронизировать ваш код и структуру БД. Чтобы обработка поля не вызывала ошибку при его отсутствии.
                                                                                            Получаете жесткую связку версии ПО и версии вашей БД.
                                                                                            Сами триггеры, признаться недолюбливаю. Они могут вызывать неожиданные последствия (например увеличивать время транзакции, которая ждет отработку триггера). Впрочем это мои личные предпочтения.
                                                                                            Ваш пример можно обработать и без триггера, если работа с данными идет через хранимые процедуры, без прямой работы с таблицами.
                                                                                            Далее получаете туже самую связку: Версия структуры БД — версия хранимок — версия ПО.
                                                                                            Не вижу тут принципиальной разницы.
                                                                                            Я работал с веберами, когда меня приглашали разрулить тормоза в БД. Логика размещена в коде. Смотрел как работают с миграциями. И почти всегда, за исключением тривиальных случаем миграции правили руками.
                                                                                            И наскакивали периодически на косяки несоответствия структуры БД и кода.
                                                                                            Ну это частные случаи, не берусь судить насколько компетентны там были команды. Бизнес у них вполне успешен, следовательно делают достаточно правильно.
                                                                                              0

                                                                                              Да со связкой-то все понятно, это очевидно. Проблема вот в чем: для обновления версии схемы с 3й до 5й вам могут понадобиться хранимки 4й версии.


                                                                                              Иными словами, история некоторых хранимок имеет значение. Именно в этом их принципиальное отличие от кода.

                                                                                                0
                                                                                                Проблема вот в чем: для обновления версии схемы с 3й до 5й вам могут понадобиться хранимки 4й версии.

                                                                                                Нет.
                                                                                                Хранимки не занимаются обновлением структуры БД.
                                                                                                Хранимки работают с данными.
                                                                                                Т.е. у 3-й версии свой набор хранимок.
                                                                                                У 5-й версии свой набор хранимок.
                                                                                                Обновление структуры БД отдельные скрипты (можно назвать их миграциями).
                                                                                                И вот обновление структуры БД может (и часто так и есть) накатываться строго последовательно.
                                                                                                Но так частенько на работающих БД.
                                                                                                Если только вы не с 0 без данных поднимаете базы, тогда у вас может быть просто набор скриптов для создания объектов БД, соответствующей версии.
                                                                                                  0

                                                                                                  Не занимаются. Но могут участвовать, прямо или косвенно.

                                                                                                    0
                                                                                                    Не занимаются. Но могут участвовать, прямо или косвенно.

                                                                                                    Все в ваших руках. Как сделаете, так и будет ;)
                                                                                                      0

                                                                                                      Ага, но способов проверить что все сделано как надо — нету. А значит, спящие ошибки будут потихоньку накапливаться.

                                                                                                        0
                                                                                                        Да как везде.
                                                                                                        Что то получается отловить на тестах, а что то вылазит все равно потом.
                                                                                                        Не видел абсолютно безошибочных систем.
                                                                                                        Вон ПО даже самолеты роняет, хотя казалось бы процедуры тестирования у них весьма жесткие.
                                                                                                          0

                                                                                                          Чтобы что-то отловить на тестах — нужно воспроизводимое окружение, а его-то как раз получить с таким подходом (миграции данных — отдельно, хранимки — отдельно) не получается.

                                                                                                            0
                                                                                                            Миграции отдельно, код приложения отдельно — не то же самое?
                                                                                                            Обычно в пакеты собирают для обновления. И код и миграции.
                                                                                                              0

                                                                                                              Нет, не то же самое: миграции данных не могут зависеть от кода, и это не чье-то пожелание, а реально существующее ограничение.


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


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

                                                                                                                0
                                                                                                                Миграции не данных, а скорее структуры БД, думаю так будет правильнее говорить.
                                                                                                                Вы можете накатить миграции, а код ваш оставить старым и приложение поломается.
                                                                                                                Следовательно миграции (в понимании скриптов для работы с обновлением структуры БД зависят от кода, также как и на наоборот) зависят от кода. Они (структура БД и код) связаны друг с другом, не независимы.
                                                                                                                Далее, мне кажется обсуждение уже скатывается в область предпочтений и личного опыта.
                                                                                                                Сохраненные процедуры и функции для того и сохраненные, чтобы не повторять одно и тоже.
                                                                                                                И работать с процедурами мне удобнее, чем продираться через нагромождение классов и прочего кода. Нагородить можно и там и там всякой труднопонимаемой лабуды.
                                                                                                                Но это уже личные предпочтения, не аргумент.
                                                                                                                  0
                                                                                                                  Вы можете накатить миграции, а код ваш оставить старым и приложение поломается.

                                                                                                                  Да, но БД при этом окажется в валидном состоянии, все ошибки изолированы в приложении.


                                                                                                                  Если то же самое сделать в схеме с миграциями и хранимками — то БД может оказаться в поврежденном состоянии, и хорошо если еще это окажется сразу же замечено.


                                                                                                                  Сохраненные процедуры и функции для того и сохраненные, чтобы не повторять одно и тоже.

                                                                                                                  В SQL нет обобщенного программирования и метапрограммирования (ну, теоретически есть exec, но он дает write-only код), поэтому иногда именно что приходится повторять одно и то же, с небольшими вариациями.

                                                                                                                    0
                                                                                                                    Если то же самое сделать в схеме с миграциями и хранимками — то БД может оказаться в поврежденном состоянии, и хорошо если еще это окажется сразу же замечено.

                                                                                                                    Отделите в голове хранимки от структуры БД и получите изолированные друг от друга набор хранимок и валидную схему БД.
                                                                                                                    Хранимки это просто код для работы с данными.
                                                                                                                    Если хранимки прошлой версии, от этого сама БД с таблицами не становится не валидной.
                                                                                                                    Из-за того, что хранимки «хранятся» в БД у вас это ассоциируется как одно. Но на самом деле, вы можете держать таблицы в одной БД, хранимки для работы в другой БД. От этого они хуже работать не станут.
                                                                                                                    Остальное на вкус и цвет.
                                                                                                                      0

                                                                                                                      Но если во время миграции отработала хранимка неправильной версии — это именно что делает БД невалидной. В ней теперь не данные, а мусор.

                                                                                                                        0
                                                                                                                        Сделать в миграции косячный код, превращающий данные в мусор, вы можете в любой системе.
                                                                                                                        Да и просто сделать запрос, превращающий данные в мусор вы можете из любого места в любой момент при наличии прав на изменение данных.
                                                                                                                        Это вовсе не зависит от хранимок.
                                                                                                                        Буквально вчера восстанавливали таблицу из бекапа (благо это справочник редко изменяемый), потому как товарищ забыл WHERE написать. Ну, бывает, что делать.
                                                                                                                          0

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


                                                                                                                          А в предложенной вами (миграции + отдельно хранимки) — ошибку можно допустить в самом механизме воспроизводимости, из-за чего косячный код успешно отработает в тестовом окружении и угробит прод.


                                                                                                                          Кстати, насчет WHERE: простая перестановка ключевых слов позволяет заметно сократить число подобных ошибок. И это тоже плюс для ORM.

                                                                                                                            –1
                                                                                                                            ORM тупо не сможет сделать наши задачи.
                                                                                                                            А в предложенной вами (миграции + отдельно хранимки) — ошибку можно допустить в самом механизме воспроизводимости, из-за чего косячный код успешно отработает в тестовом окружении и угробит прод.

                                                                                                                            Не знаю, что такое механизм воспроизводимости.
                                                                                                                            Чем косячный код из процедуры (который по сути своей набор запросов) отличается от косячного кода в некоем файле (который суть набор запросов) не вижу разницы.
                                                                                                                            И почему косячный код превращающий данные в мусор из файла отловится на тесте, а такой же косячный код из хранимой процедуры не отловится на тесте не могу понять.
                                                                                                                            Тут вы уже натягиваете сову на глобус.
                                                                                                                            Новых аргументов не увидел, извините.
                                                                                                                              0

                                                                                                                              Потому что в одном случае миграция БД от версии 3 до версии 5 дает такой же результат, что и миграция от версии 3 к версии 4, а потом к версии 5.


                                                                                                                              А в другом случае результат может оказаться разным.

                                                                                                                                0
                                                                                                                                Хорошо.
                                                                                                                                Пример.
                                                                                                                                В версии 4 добавилось поле.
                                                                                                                                Миграция добавляет поле 1.
                                                                                                                                В версии 5 добавилось другое поле.
                                                                                                                                Миграция добавляет поле 2.
                                                                                                                                Т.е. не накатив миграцию 4, как вы получите в БД поле 1?
                                                                                                                                И при чем тут бизнес логика в процедурах?
                                                                                                                                Вы точно не смешиваете разные понятия?
                                                                                                                                  0

                                                                                                                                  Почитайте комментарии выше.


                                                                                                                                  Версия 3 содержит некоторую версию хранимки X (далее X3)


                                                                                                                                  Версия 4 содержит другую версию хранимки X (далее X4)


                                                                                                                                  Версия 5 содержит миграцию Y, которая, в том числе, запускает X


                                                                                                                                  Теперь, если мигрировать 3-4-5, то миграция Y запустит хранимку X4. А если мигрировать 3-5 — то есть два варианта:


                                                                                                                                  1. обновления хранимок — тоже миграции. Все в порядке, миграция Y все еще запускает хранимку X4.


                                                                                                                                  2. обновления хранимок происходят после всех миграций. Вот тут уже проблема: миграция Y теперь запустит хранимку X3.


                                                                                                                                    0
                                                                                                                                    Давайте определимся что есть миграция?
                                                                                                                                    В моем понимании:
                                                                                                                                    Миграция это набор скриптов приводящих БД к состоянию Х из состояния Y.
                                                                                                                                    Я не могу понять, зачем миграция должна запускать хранимую процедуру?
                                                                                                                                    И если вы допускаете, что миграция 5 может стартовать после миграции 3, значит вы должны обеспечить механизмы для этого.
                                                                                                                                    Например, вы обеспечиваете сначала запуск миграции 4, потом уже запускаете миграцию 5.
                                                                                                                                    Или в миграции 5 делаете проверку состояния БД, в какой версии она находится из предыдущих и для каждой версии свою ветку скриптов.
                                                                                                                                    Собственно это все.
                                                                                                                                    Это частный технический вопрос, как привести структуру БД и данных в нужное вам состояние Х.
                                                                                                                                    Причем тут бизнес логика в процедурах? Это совершенно другой вопрос.
                                                                                                                                      0
                                                                                                                                      Я не могу понять, зачем миграция должна запускать хранимую процедуру?

                                                                                                                                      Так случилось. Если это не ограничено технически — значит, рано или поздно это случится.


                                                                                                                                      И если вы допускаете, что миграция 5 может стартовать после миграции 3, значит вы должны обеспечить механизмы для этого. Например, вы обеспечиваете сначала запуск миграции 4, потом уже запускаете миграцию 5.

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


                                                                                                                                      Причем тут бизнес логика в процедурах?

                                                                                                                                      Напрямую — не при чем. Но она хоть как-то удобна только когда хранимые процедуры заливаются в базу напрямую, без миграций. В противном случае же любое редактирование хранимки — это создание новой копии файла, что мешает "родным" механизмам git проводить слияния изменений.

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

                                                                                            Ну вот есть у меня ветка задачи, когда-то от основной ветки отрезанная. Я сделал свои процедуры или изменил сществующие, пускай с десяток изменений — проверил всё работает. Подмерживаю основную ветку, чтобы проверить, что последние изменения не ломают мою задачу, а мои изменения не ломают их. За это время в основной ветке с десяток процедур добавилось, а ещё три десятка изменилось. Всего их, например, под 1000 (аналог сотни объектов с десятком методов в каждом — несложная система). Как мне сделать эту проверку?


                                                                                            Смотреть какие файлы изменились/создались за время последнего синка с основной веткой и накатывать их по одному? Сносить всю базу и разворачивать её с нуля?


                                                                                            Сделал задачу, отправил её на код-ревью, переключаюсь на другую. В базе у меня версии от предудщей задачи, как мне переключиться на версию основно ветки — удалять новые процедуры ручками по памяти или делать дифф vcs, накатывать старые версии так же по памяти лили диффу, или нактывть новую базу?


                                                                                            На основная суть: процедура это код в виде текстового файла

                                                                                            Все более-менее рабочие тулзы и подходы по использованию VCS для SQL базируются на том, что под контролем VCS хранятся не коды процедур, а команды на создание или обновление процедур (возможно создание с предшествующим удалением), которые уже содержать имя и код процедуры. Императивный подход, а не декларативный. Мы редактируем не процедуру, а команду на её создание или обновление. А если, не дай бог, для раскатывания процедур применяются миграции, то мы и не редактируем процедуру, а на кажды чих создаём новую команду на изменение, н уи удаление.

                                                                                              –1
                                                                                              Ну вот есть у меня ветка задачи, когда-то от основной ветки отрезанная. Я сделал свои процедуры или изменил сществующие, пускай с десяток изменений — проверил всё работает. Подмерживаю основную ветку, чтобы проверить, что последние изменения не ломают мою задачу, а мои изменения не ломают их. За это время в основной ветке с десяток процедур добавилось, а ещё три десятка изменилось. Всего их, например, под 1000 (аналог сотни объектов с десятком методов в каждом — несложная система). Как мне сделать эту проверку?

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

                                                                                              У меня ощущение, что вы теоретически все это представляете.
                                                                                              Вы реально работали с системами, где бизнес логика работает в хранимых процедурах?
                                                                                              Мы работаем (уже не на первом месте работы) и ваши фразы они даже не звучат. «Иперативный подход, декларативный подход» — зачем вносить не нужные понятия в простые вещи?
                                                                                              Звучит так: взял код процедуры из контроля версий, доработал, положил обратно в контроль версий.
                                                                                              И называется это: «Редактирование процедуры».
                                                                                              Затем где то создается набор скриптов в специальном ПО (в банке), а где то просто накатываются скрипты для обновления на сервере.
                                                                                              Коллизии одновременной работы разруливаются так же как разруливаются проблемы с кодом при любой коллективной работе, не вижу в этом каких то мега отличий и принципиальной разницы.
                                                                                              Как протестировать изменения, если другие разработчики внесли тоже изменения? Это же общая задача при разработке. Все аналогично.
                                                                                              В общем, если бы я сидел точил код в одиночестве и теоретически это представлял, наверное я бы засомневался.
                                                                                              Но я уже много лет работаю с системами, в которых бизнес логика зашита в код процедур и не вижу неразрешимых противоречий, да просто неудобства не вижу.
                                                                                              Помню тут статью из Яндекса: «Мы перевели БД на PostgreSQL. Поскольку логика в процедурах это боль, мы решили ее вынести в код. Что то вынесли, но оказалось, что все вынести не возможно, в таком случае система не тащит по производительности. Пришлось часть оставить в процедурах.»
                                                                                              Т.е. на мой взгляд они сделали хуже. Они теперь логику ловят в двух местах.
                                                                                              В общем мой вывод пока что: Дело привычки.
                                                                                                0
                                                                                                Вы реально работали с системами, где бизнес логика работает в хранимых процедурах?

                                                                                                Я вот работал.

                                                                                                  0
                                                                                                  А как вы проверяете сейчас? Все тоже самое.

                                                                                                  Просто проверяю. Рабочий каталог под контролем VCS или прямо содержит исполняемый код (скриптовые языки) или рабочий каталог компилируется в него, а компилятор — чистая функция от исходников по сути. Состояние проекта полностью лежит под контролем VCS, нет ничего (ну, почти ничего) внешнего, у чего было бы своё состояние, от которого зависит воспроизводимость запусков.


                                                                                                  Пока не появляется SQL или типа того, когда у нас нет ни желаемого состояния в проекте, ни удобных (в идеале прозрачных) механизмов приведения к нему. Если мы храним процедуры или схему данных в виде явных или завуалированных команд CRATE/ALTER/DROP/..., то мы лишь надеемся, что эти команды будут исполнены на том состоянии базы, на котором они исполнились у нас. Со схемой данных более-менее решено путём декларативного описания таблиц, связей и т. п. и генерацией команд для приведения текущего состояния (реально текущего, физически запрашивается текущая схема у СУБД) к желаемому. С самими данными сложнее, а с процедурами более-менее работающего способа нет, кроме как дропнуть все и создать заново при каждой смене ветки, мерже, пулле. Уж не знаю почему, но реализуют генераторы команд CRATE/ALTER/DROP для процедур и триггеров, которые бы сравнивали текущее состояние процедур в базе и их текстовое представление в файлах.


                                                                                                  Звучит так: взял код процедуры из контроля версий, доработал, положил обратно в контроль версий.
                                                                                                  И называется это: «Редактирование процедуры».

                                                                                                  Согласитесь, что это не реадктирование процедуры по факту у вас, если я правильно понял, а редактирование запроса создания/редактирования процедуры?


                                                                                                  Как протестировать изменения, если другие разработчики внесли тоже изменения? Это же общая задача при разработке. Все аналогично.

                                                                                                  У меня вопрос не как протестировать, а как привести процедуры базы к ожидаемому состоянию. Вот сейчас в базе у меня 1000 процедур с мастер-ветки (1000 файлов с CREATE OR REPLACE PROCEDURE), я переключаюсь в ветку, где 1010 таких файлов, причём 20 новых, 10 удалено, а 30 изменено. Я ожидаю, что после чекаута в эту ветку у меня будет 1010 процедур в базе, причём физически на сервер уйдёт 60 запросов. Что мне нужно сделать?

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

                                                                                Обрабатывать, возможно, быстрее. В некоторых случаях. А удобнее в коде, где есть средства переиспользования кода, управления выполнением, возможность использовать дополнительные сервисы типа произвольного кеширования, и т.п. Я поддерживаемость имел в виду.


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

                                                                                Затем что там удобнее управлять кодом обработки.


                                                                                Кстати, интересен был бы практический пример, какая логика описывается языком программирования в приложении?

                                                                                Ну собственно любая. Проверка прав доступа на выполнение действия например. Работал с базой, где в каждой процедуре был скопирован один и тот же код проверки прав с выдачей нужного сообщения, с соответствующими исправлениями в каждой копии названий таблиц и переменных, и соответствующими же проблемами, когда исправлено не все и не везде, особенно когда в вызываемую функцию добавился новый параметр. Да и вообще любая, связанная с наследованием и частичным переопределением в наследниках. Сложить A и B конечно везде несложно.

                                                                                  0
                                                                                  Что мешало разработчику создать отдельную функцию check_operation_ACL($user_id, $table_name, $operation_id)
                                                                                  которая бы запускалась в нужных хранимках.
                                                                                  SQL точно так же умеет «переиспользование кода»
                                                                                  Я поддерживаемость имел в виду.

                                                                                  К сожалению, в моей реальности чаще проще поддерживать логику в самом SQL, тк разработчик ERP-системы не в состоянии сделать функционал редактируемой администратором логики в нужных местах.
                                                                                  Плюс встроенный в ERP язык программирования не умеет многие вещи.
                                                                                  Если про поддерживаемость имеется ввиду версионность кода, и кто когда что сломал, то это одинаковая организационная проблема, какой сохранять код, или из SQL, или из конфигуратора системы в отдельный репозиторий.
                                                                                    0

                                                                                    А переделать исходный код (при наличии доступа к нему) — еще проще, чем переделать логику в SQL.

                                                                                      0
                                                                                      А если приложение работает в режиме толстого клиента? Попробуйте заменить EXE-файл на терминальном сервере, на котором работает 50 пользователей, и еще на на паре сотне отдельно стоящих компьютеров.
                                                                                        0

                                                                                        Если автообновление есть и работает — никаких проблем. Если же нет — ну и кто тут виноват?

                                                                                          0
                                                                                          Не так выразился, нельзя заменить exe-файл, пока запущен хоть один экземпляр программы, сначала всех выгнать из программы, потом обновлять. И так несколько раз в течение рабочего дня.
                                                                                          Это не проще, чем переделать логику в SQL.
                                                                                            0

                                                                                            А почему не у каждого своя копия программы, с обновлением при запуске?

                                                                                              0
                                                                                              У каждого способа есть свой фатальный недостаток и куча нюансов. Нюансов системы лицензирования, изменился путь программы — новое рабочее место. Нюансы системы безопасности, запуск exe откуда-либо кроме program files и windir запрещен. Права на запись в program files тоже закрыты, значит нужно как-то заранее каждому создавать свою копию программы с директорией, и потом всю эту кучу отдельно обновлять.
                                                                                                0
                                                                                                Нюансов системы лицензирования

                                                                                                Если у вас есть доступ к исходному коду (в т.ч. на изменение) — то это ваша программа. Неужели так трудно самим себе правильную лицензию оформить? :-)


                                                                                                запуск exe откуда-либо кроме program files и windir запрещен

                                                                                                Но при этом к единственной копии СУБД админский доступ есть у любого разработчика? А доступ на запись — у любого пользователя (пусть и частично защищенный слоем хранимок)? Ну ок...

                                                                                              0

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

                                                                                        0

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


                                                                                        Поддерживаемость в любом смысле, касающемся управления кодом.

                                                                                          0
                                                                                          Что именно мешает придти к точно такому же бардаку в самом веб-приложении? Для этих мест роли могли считаться так, а в других местах по-другому. Это все вопросы организации внесения изменений и работы с legacy-кодом.
                                                                                            +2

                                                                                            А для веб-приложения есть IDE, в которой можно сравнительно легко разобраться что и откуда растет.


                                                                                            Для SQL же я ничего столь же мощного не встречал.

                                                                                              0

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

                                                                                              –1

                                                                                              Так вроде и для СУБД разрешения можно контролировать внутренними механизмами, без всяких процедур.


                                                                                              GRANT <permission> [ ,...n ] ON   
                                                                                                  [ OBJECT :: ][ schema_name ]. object_name [ ( column [ ,...n ] ) ]  
                                                                                                  TO <database_principal> [ ,...n ]   
                                                                                                  [ WITH GRANT OPTION ]  
                                                                                                  [ AS <database_principal> ]

                                                                                              Вот это вот всё. А то делают GRANT ALL, а потом начинают извращаться с движками проверки ролей в тридевятом царстве, а сами данные тем временем висят голым задом по system@system, и утекают при первой же возможности.

                                                                                                +2
                                                                                                Имеются ввиду права на бизнес-обьекты. Например, может ли пользователь редактировать объект созданным другим пользователем, или может ли простой менеджер отредактировать документ уже подписанный начальником отдела. Физически записи лежат же в одной таблице.
                                                                                                  –1

                                                                                                  Можно ведь сделать Updatable View, а доступа к самой таблице не давать в принципе. Если совсем строго, можно Updatable View делать на базе Readable View, и к ним иметь разные разрешения на чтение и запись, потому что если умеет обновлять, то должен уметь и читать, а обратное уже неверно.


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

                                                                                                    0

                                                                                                    А если роли непредопределённые и пользователь их конфигурит сам? Генератор вьюшек писать?

                                                                                                      0

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


                                                                                                      А если пользователь настраивает разрешения сам, то мы находимся в else моего предыдущего сообщения, и определение разрешений средствами СУБД уже не очень хорошо работает само по себе. Зато у нас есть одно из двух решений:


                                                                                                      • Разрешения тоже являются данными, и их некоторые серверы разрешений и вне SQL плохо понимают, нужен будет такой, который поймёт. При этом в самой базе скорее всего придётся-таки устроить free-for-all, где все читают всё, и надеяться что БД не скомпрометируют.
                                                                                                      • Мы можем пользователям сделать красивый интерфейс для работы с нативными разрешениями СУБД, но опять же ценой вывешивания этого интерфейса фактически в открытый доступ, под какой-нибудь ролью суперадминистратора. И иметь ассоциации ролей с какими-нибудь данными, чтобы не было возможности менять чужие разрешения, а только свои.

                                                                                                      При этом ни для одного из вами озвученных вариантов требований нет простого пути позволить пользователям решать "может ли пользователь редактировать объект, созданный другим пользователем, или может ли простой менеджер отредактировать документ уже подписанный начальником отдела". Если вьюшки мы считаем моветоном, тогда единственный более-менее реалистичный механизм работы здесь — это императивные проверки в клиенте, где пользователю будет дан чекбокс, оные проверки выключающий, и на этом его конфигурение будет закончено. Проверки, вероятно, нужно будет выразить как некий DSL, чтобы его понимал и фронт, и сервер, либо дублировать несколько раз. На UI это нужно для отзывчивости, и на сервере для надёжности, потому что полное доверие UI в итоге обходится дорого.


                                                                                                      Кстати, а чем плох генератор вьюшек? Ну, кроме того, что его, гипотетически, надо писать?
                                                                                                      Кстати, не согласитесь ли вы ли вы, что ORM и есть такой генератор вьюшек, только рантайме (в общем случае)? А если "вьюшки" из релиза в релиз не меняются, зачем их генерировать каждый раз, не проще ли будет поместить их сразу в СУБД?

                                                                                                        0
                                                                                                        Если роли неопределённые, тогда у вас нет ролей.

                                                                                                        Не неопределённые, а неПРЕДопределённые, максимум три роли при первом запуске: анонимус, суперадмин и зарегистрировнній пользователь.


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

                                                                                                        Угу, завести в базе 100500 пользователей и апп-сервер будет держать соединение для каждого.


                                                                                                        Кстати, а чем плох генератор вьюшек? Ну, кроме того, что его, гипотетически, надо писать?

                                                                                                        100500 пользователей, 100500 вьюшек для каждой таблицы? Ну пускай не для каждой, джойны сделаем к тому, что и так джоинится. Ну сдесяток тоно выйдет. Миллион вьюшек?


                                                                                                        А если "вьюшки" из релиза в релиз не меняются, зачем их генерировать каждый раз, не проще ли будет поместить их сразу в СУБД?

                                                                                                        Они редко меняются, но постоянно создаются — пользователи-то регистрируются.

                                                                                                          –2
                                                                                                          Угу, завести в базе 100500 пользователей и апп-сервер будет держать соединение для каждого.

                                                                                                          А это разве хуже чем если каждый пользователь фактически с базой общается под аккаунтом администратора, где по факту имеет все разрешения на чтение и запись (и хорошо если и не на все ddl-операции тоже, до кучи), и только ваша прослойка с ещё одним сервером контроля разрешений сохраняет ваши данные от компрометации. То есть, доступ ко всем всем вашим данным можно получить если узнать, под каким аккаунтом ваш аппсервер общался с базой, а такой аккаунт у всех один.


                                                                                                          100500 пользователей, 100500 вьюшек для каждой таблицы

                                                                                                          Ну если у вас требования такие, что ж поделать. Не руками ведь вам их писать, вы генератор сделали. Если хотите ограничить число сущностей — улучшите генератор, чтоб вьюшки были параметризованы, например, пользователем, и/или отслеживайте (случайные) совпадения по условиям, ведь запросы у такого числа людей редко уникальны. А раз условия не уникальны, можно оптимизировать и выдать двум пользователям одну и ту же вьюшку(но параметризовать пользователем всё равно, во имя справедливости). И тогда их будет может быть уже 50250, а может и того меньше.


                                                                                                          Кстати, а как вы предложите решать эту задачу без вьюшек? Ну, в смысле, у вас вместо 100500 вьюшек будет 402000 уникальных, сгенерированных вашим data-store в рантайме, запросов? Или есть какие-то мне неизвестные средства, о которых я просто не подумал?

                                                                                                            0
                                                                                                            А это разве хуже чем если каждый пользователь фактически с базой общается под аккаунтом администратора

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


                                                                                                            и только ваша прослойка с ещё одним сервером контроля разрешений сохраняет ваши данные от компрометации

                                                                                                            Ну да.


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

                                                                                                            Ну или узнать под каким аккаунтом DBA логинится или скрипты изменения схемы. Секреты надо хранить одинаково.


                                                                                                            Кстати, а как вы предложите решать эту задачу без вьюшек? Ну, в смысле, у вас вместо 100500 вьюшек будет 402000 уникальных, сгенерированных вашим data-store в рантайме, запросов?

                                                                                                            Зависит от драйвера СУБД, скорее всего ему на вход будут приходить параметризированные запросы под юзера для прав, которые легко разрулить на уровне SQL запроса, а остальніе будут проверяться либо до запроса к основным данным, либо после, либо и до, и после.

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

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

                                                                                                                0

                                                                                                                Разрешения на изменение схемы — часть схемы. А данные о доступах к данным могут храниться совсем в другой СУБД или вообще не в СУБД.

                                                                                        +1
                                                                                        Где заканчивается обработка данных и начинается логика?
                                                                                        Вот здесь логика или обработка?
                                                                                        update clients set description=(
                                                                                        case when balance < 100500 then 'злостный должник'
                                                                                        else 'должник' end)
                                                                                        where balance < 0

                                                                                        Уже столько раз наталкивался, что очередной ORM, вместо указанного выше запроса делает так:
                                                                                        
                                                                                        request1:
                                                                                         select * from clients where balance < 0
                                                                                        ...
                                                                                        request2:
                                                                                        update clients set description='должник'
                                                                                        where clients_id in (сотни значений)
                                                                                        

                                                                                        а иногда вообще хочется плакать горькими слезами от select * from clients
                                                                                        потому, что программист в параметрах Linq написал IEnumerable вместо IQueryable…
                                                                                        По факту у нас спор остроконечников и тупоконечников.
                                                                                          0
                                                                                          Вот здесь логика или обработка?

                                                                                          Я имел в виду поддерживаемость кода, а не логическое разделение)


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

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


                                                                                          Но такая замена это конечно неправильное поведение.

                                                                                            0
                                                                                            Конкретно данный пример был упрощен до предела. Конечно, там будет какой-нибудь set debt_status=15 и в условии where может быть нагромождение exist(select blabla)
                                                                                            И таких статусов у клиента штук 20, и пишутся в отдельную таблицу с историей. И есть вьюха на текущий статус из этой истории.
                                                                                            И в некоторых случаях VIEW значительно замедляет конечные запросы, например, а теперь из базы в пару десятков миллионов клиентов вывести количество должников по состоянию на начало года, и плюс эти должники должны быть с каким-нибудь другим статусом, или вообще потерявшим этот статус в прошедшем году.
                                                                                              0

                                                                                              А зачем тогда VIEW, если замедляет? Делаем просто SELECT * FROM clients WHERE balance < 0 и выводим в представлении как нужно. Поиск по истории это сама по себе непростая задача, ORM тут ни при чем. Будет что-то вроде SELECT * FROM clients WHERE id IN (SELECT client_id FROM history WHERE ...), и тут как раз удобнее разбить на 2 запроса с offset/limit в первом, в IN будет не более limit идентификаторов.

                                                                                            0

                                                                                            Вы привели очень частный случай. Почему-то в моей практике так делать приходится довольно редко...


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

                                                                                              0
                                                                                              Странно, довольно часто приходится бороться с заказчиком, который хочет поставить атрибут архивный для документов или клиентов. Начинаешь его пытать, а зачем, а какие критерии, а там выясняется всякие детали, типа, клиенты по которым не было движения больше трех лет, чтобы не попадали в общий список поиска и тд… или чтобы клиенты, которые заключили документы в пятницу 13, и родились в год козы, в общем списке подсвечивались цветом с кодом 666. А запихаешь такое во вьюху, простой select top 50 columns from clients left join view начинает дико тормозить.
                                                                                                0

                                                                                                Ну так есть же куча вариантов как с такими поступать:


                                                                                                1. "сырой" запрос либо хранимка;
                                                                                                2. ставим признак заранее, при сохранении;
                                                                                                3. добавляем условие чтобы не ставить признак повторно — и вот уже нет ничего страшного "обычном" ORM-подходе, ведь каждый объект будет обработан не более одного раза, а на 1 раз много ресурсов не потребуется.
                                                                                                  0
                                                                                                  2) этот атрибут бизнес может придумать в произвольный момент времени.
                                                                                                  3) статус может измениться в произвольный момент времени, даже из-за изменения критериев расчета атрибута. Например, с 2019 года мы любим всех клиентов, родившихся в год козы, а в прошлом году мы их ненавидели.
                                                                                                  Я утрирую конечно, но ¯\_(ツ)_/¯
                                                                                                    0
                                                                                                    статус может измениться в произвольный момент времени, даже из-за изменения критериев расчета атрибута

                                                                                                    В таких условиях никакой update работать корректно не будет. Тут только сложный и тормозной select поможет — а вот его-то как раз ORM составлять помогает :-)

                                                                                              0

                                                                                              По такому запросу все автоматом становятся злостными, ибо 0 явно меньше чем 100500

                                                                                                +1
                                                                                                Надо правильные ORM для таких задач выбирать. EF хорош писать сайты быстро, но про скорость забудьте, ее придется тюнать.
                                                                                                На linq2db это пишется с полпинка:

                                                                                                var obligors = from c in db.Clients
                                                                                                   where c.Balance < 0
                                                                                                   select c;
                                                                                                
                                                                                                obligors
                                                                                                    .Set(p => p.Description, p => p.balance < -100500 ? "злостный должник" : "должник")
                                                                                                    .Update();

                                                                                                Можно таким же способом их удалить
                                                                                                obligors.Delete();
                                                                                                или вставить в другую таблицу не пишучи SQL.
                                                                                                obligors.Insert(db.Others);

                                                                                                Все происходит на сервере, ничего на клиент не тянется.
                                                                                          0
                                                                                          [совсем offtop]
                                                                                          и будет раз в сутки
                                                                                          Это все-таки не дело. Один вопрос с вами ругаться, другой — в РО загонять.
                                                                                          Поправил, как мог.
                                                                                          [/совсем offtop]
                                                                                            0

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


                                                                                            Иногда этого общего подмножества достаточно. Иногда — нет (и пример данной статьи говорит именно об этом).

                                                                                              –1
                                                                                              Конечно периодически идут рассмотрения перехода на другую СУБД. Это всего выходит очень дорого с неопределенным результатом.

                                                                                              Собственно потому и дорого с неопределнным результатом, что надо перписывать практически весь код взаимодействия с СУБД, если вы выжимаете из текущей всё. ORM, query builders или вручную написанніе запросы — не суть, суть используете вы специфику конкретной СУБД или абстрагированы от неё, пускай даже абстракция уровня "запросы пишем ручками, но из специфичных штук используем исключительно особенности синтаксиса"

                                                                                                0
                                                                                                Все верно.
                                                                                                Только вот без использования специфики конкретной СУБД не получается. С этой спецификой то в натяг идем.
                                                                                                И даже если писать без специфики, как видно из статьи обсуждаемой в том числе, все равно, если задаться целью сделать мультиСУБД продукт, возникают дополнительные расходы. Оправданы ли они, нужно хотя бы попытаться рассмотреть в каждом конкретном случае. Мне не знаю, повезло или не повезло, создавать такие продукты, где было бы оправдано это не приходилось.
                                                                                                Переход из одной СУБД в другую, в частности из MS SQL в PostgreSQL делал, но вот что бы оправдалось мультибазовость, пока не попадалось.
                                                                                              0

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


                                                                                              Для чего вообще может потребоваться менять бд? Либо если текущая перестала поддерживаться, либо если конкуренты сделали прорыв в производительности. Чтобы избежать первого, нужно использовать популярную надёжную бд, вроде постгреса. Второе, по моему, просто невозможно в реляционных бд — они уже полвека пилятся, всё что можно было действительно сильно оптимизировать в движке — уже оптимизировали.

                                                                                                0

                                                                                                Ещё вариант: у конкурентов была лучшая производительность и другие плюсы на одних кейсах и какие-то минусы на других. На старте проекта эти минусы были значимыми, а те кейсы не предвидились. Со временем ситуация поменялась, и, например, на MySQL уже новые бизнес-требования как функциональные, так и не очень не реализовать без ОГРОМНЫХ костылей типа создания для частичных или функциональных индексов отдельных столбцов, заполняющихся по триггерам, а то и целых таблиц. Тоже с материализованным представлениями и т. п.

                                                                                                0
                                                                                                Ну, давайте поговорим о том, какое это «просто хранилище» и об использовании пространственных функций PostGIS, например. Замените их чем-нибудь эффективно.
                                                                                                  0
                                                                                                  Это реалистично только для определённого класса задач. Но, далеко, не во всех случаях. Реляционные СУБД — это не только хранение данных, но и стандартизированный доступ к данным, поддержка логической целостности данных и много чего ещё. «просто хранилище данных» — несколько наивный взгляд. Если в приложении реально нужно только хранилище — то хоть СУБД, хоть простые файлы — один чёрт. «Использовать любую БД», «использовать любую ОС», «использовать любой ЯП», «использовать любого программиста» — и т.п. — все эти абстракции работают только до определённого предела и накладывают массу ограничений на продукт. Те, кто укладывается в это «прокрустово ложе» — вполне счастливы, но это точно не всем подходит.
                                                                                                    +1
                                                                                                    «Использовать любую БД», «использовать любую ОС», «использовать любой ЯП», «использовать любого программиста» — и т.п. — все эти абстракции работают только до определённого предела и накладывают массу ограничений на продукт.

                                                                                                    Вы хорошо сформулировали, спасибо. Положу себе в копилку памяти.
                                                                                                  +8
                                                                                                  Я конечно заранее извиняюсь, но по моему должно быть стыдно, среди существенных минусов перечислять такие вещи как:
                                                                                                  С MySQL не получалось эффективно поддерживать вложенные группы

                                                                                                  Эта проблема решена в mysql 8 с введение WITH, а значит можно было только повысить требование к версии.

                                                                                                  MySQL не добавит тип столбца TEXT, если не задать параметр length

                                                                                                  ИМХО вообще мелочь, больше похожая на придирки к синтаксическому сахару.

                                                                                                  p.s. если у кого то есть конструктивные возражения с аргументами, с радостью выслушаю.
                                                                                                    +1
                                                                                                    посгрес дохнет под серьезной нагрузкой из-за тормозных транзакций и сборки мусора, но mysql/innodb еще печальней с транзакциями. попробуйте сделать innodb табличку без индексов и в двух параллельных транзакциях записать по записи, а потом в одной из транзакций удалить свою же запись. вывалится с deadlock
                                                                                                    dba.stackexchange.com/questions/238756/mysql-innodb-trying-to-lock-uncommitted-row-from-parallel-transaction-deadlock

                                                                                                    при фулскане оно пытается наложить локи на все, даже на не незакомиченные записи.
                                                                                                      0
                                                                                                      Момент, но я писал про эффективность поддерживать вложенные группы и параметр length, и именно про это ждал комментарии(если кто то решит что я не прав по этому поводу), и только. По поводу всего остального я знаю)
                                                                                                        +3
                                                                                                        попробуйте сделать innodb табличку без индексов

                                                                                                        Можно. А зачем? Кто в здравом уме будет делать табличку без индексов?
                                                                                                          +1
                                                                                                          что бы воочию увидеть как mysql пытается поставить локи на незакомиченные записи соседней транзакции.
                                                                                                          что касается индексов, то во первых в оракле мне не приходит в голову индексировать абсолютно каждое поле. во вторых повторюсь — дело в фуллскане, а не индексах. индекс лишь снижает вероятность, но не отменяют фулскан. например у меня лезли дедлоки на таблице с индексом, но записей было мало и mysql применял фуллскан не смотря на индекс. по идеи в запросах где вычитывается более половины записей таблицы тоже фулскан должен быть.
                                                                                                            +1
                                                                                                            Хах, я тоже так думал. Пока один знакомый в одной из топовых организаций страны не пожаловался, что их хранилище данных — это просто ворох таблиц без связей и индексов, и что поэтому у них постоянно что-то теряется, что-то дублируется. Потом встречался с сокурсником из топового интегратора, который участвовал в проектировании этого хранилища на позиции архитектора, и на мой вопрос он ответил: «Ну а что, мы всегда так делаем, под индексами там данные не зальёшь/не изменишь — это оптимизация». У меня из одного вопроса «почему?» осталось два: «а зачем тогда оно такое надо» и «за что они получают астрономические деньги».
                                                                                                              0
                                                                                                              что бы получить опыт и осознать почему технологии бигдаты неизбежны с какого-то объема. если речь о хранилище то ты просто не зальешь за вменяемый промежуток времени данные с врубленными FK и индексами. а всякие скоринги и фрауд детекшены уже не нужны спустя несколько часов. потому сначала отключают FK и индексы при заливке, а потом переезжают на хадупы где индексов и FK нет в принципе, а валидация связей — часть ETL процесса интеграции данных в хранилище. если вырубать FK и вовсе не отслеживать зависимости то да, болото данных гарантированно.
                                                                                                              но это про хранилища, тут же у меня скорее речь про oltp, где у mysql умудряются сталкивается транзакции, между которыми ничего общего.
                                                                                                            +2
                                                                                                            Я вас немного расстрою, с вашего позволения: в любой СУБД легко, не понимая базовой матчасти (блокировки/уровни изоляции), создать подобную ситуацию. У вас ровно этот пример.
                                                                                                              –2
                                                                                                              давай. попробуй расстроить. я поржу.
                                                                                                              в любой версионной субд есть row level блокирование и подобные ситуации, где сталкиваются транзакции не имеющие ничего общего не возможны. уровни изолированности транзакций и блокировки разводят транзакции затрагивающие общие данные, а в примере у каждой транзакции своя запись, не имеющая никакого отношения к другим транзакциям.
                                                                                                                +2
                                                                                                                Странный ответ. Я пишу про блокировки/уровни изоляции. Вы мне отвечаете про блокировки/уровни изоляции (версионные), подтверждая написанное, но выглядит это так, как будто вы с чем-то спорите.
                                                                                                                  –2
                                                                                                                  чего не ясного? уровни изоляции описывают допустимые коллизии транзакций, обращающиеся к одним и тем же наборам данных. ключевое — одни и те же наборы, я же показываю что у mysql все на столько плохо, что коллизии возникают даже у транзакций, что обрабатывают разный набор данных. уровни изоляции тут не причем.
                                                                                                                    +2
                                                                                                                    уровни изоляции тут не причем
                                                                                                                    Именно от уровня изоляции зависят блокировки. С каким-нибудь read committed, например, вы тут получите блокировку на странице данных, где оказались ваши разные наборы данных, и на этом удивленно повиснете.
                                                                                                                      –2
                                                                                                                      ты путаешь эскалацию блокировок с уровнями изолированности. эскалация блокировок никакого отношения не имеет ни к уровням изолированности, ни к mysql. mysql утверждает что у него row level блокировки. но врут.
                                                                                                                      RC с row level блокировками не должен накладывать какие либо блокировки на данные, не имеющие никакого отношения к этой транзакции. то что на странице посторонние данные, не нужные транзакции не повод их блокировать.
                                                                                                                        +2
                                                                                                                        Это вообще не эскалация. Эскалация — это когда блокировок ключей на странице достаточно много. При хранении в куче это «by design».

                                                                                                                        попробуй расстроить
                                                                                                                        ты путаешь
                                                                                                                        Мы разве знакомы?
                                                                                                                          –2
                                                                                                                          когда блокируется больше строк, чем необходимо это эскалация. эскалация к уровням изолированности транзакций никакого отношения.

                                                                                                                          Мы разве знакомы?

                                                                                                                          вы придется заслужить «пониманием базовой матчасти» (тм)
                                                                                                                            +2
                                                                                                                            когда блокируется больше строк, чем необходимо это эскалация
                                                                                                                            Я выше написал, что такое эскалация. Поучите базовую матчасть, пожалуйста. Начать можно отсюда:
                                                                                                                            Lock escalation is the process of converting many fine-grained locks (such as row or page locks) into table locks.
                                                                                                                            До понимания базовых терминов, извините, говорить не о чем.
                                                                                                                              –3
                                                                                                                              матчасть я выучил 20 лет назад, 15 лет как сертифицированный ocp. так что дальнейшее разжевывание лишь за деньги. конвертация row level блокировки в page lock приводит блокировке посторонних строк, не имеющих отношения к транзакции. эскалация никакого отношения к уровням изолированности не имеет.
                                                                                                                              С каким-нибудь read committed, например, вы тут получите блокировку на странице данных

                                                                                                                              RC требует блокировать лишь необходимые транзакции строки. получить блокировку целой страницы можно исключительно в результате эскалации, которая к уровням изолированности транзакций параллельна.
                                                                                                                                +2
                                                                                                                                15 лет как сертифицированный ocp
                                                                                                                                Вы мне предлагаете начать обсуждение уровня ценности сертификатов над уровнем плинтуса? Откажусь, пожалуй, даже несмотря на такую подачу.

                                                                                                                                конвертация row level блокировки в page lock приводит блокировке посторонних строк, не имеющих отношения к транзакции
                                                                                                                                Ну вот, хоть что-то полезное по ссылке вычитали. Вот только никакого отношения эта конвертация (которая и есть та самая эскалация) к описываемому случаю страничной блокировки не имеет.

                                                                                                                                получить блокировку целой страницы можно исключительно в результате эскалации, которая к уровням изолированности транзакций параллельна
                                                                                                                                Все-таки читать про блокировки. Подсказка для поиска: страничная блокировка при вставке в кучу без блокировки ключей. Даже при вставке одной строки — это хотя бы должно дать понимание, что эскалация тут вообще не при чем и упоминать ее — очень явно выказывать полное непонимание как происходящего, так и самой терминологии.
                                                                                                                                  –1
                                                                                                                                  Ну вот, хоть что-то полезное по ссылке вычитали. Вот только никакого отношения эта конвертация (которая и есть та самая эскалация) к описываемому случаю страничной блокировки не имеет.

                                                                                                                                  не имеет и тебе доступно разжевал почему. уровни изоляции и эскалация абсолютно не пересекающиеся понятия. т.е. вот тут ты несешь дважды пургу
                                                                                                                                  С каким-нибудь read committed, например, вы тут получите блокировку на странице данных

                                                                                                                                  а вот тут трижды
                                                                                                                                  Все-таки читать про блокировки. Подсказка для поиска: страничная блокировка при вставке в кучу без блокировки ключей.

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

                                                                                                                                    +1
                                                                                                                                    Для новичка, который притянул сюда не имеющую отношение к происходящему эскалацию блокировок только потому, что еще вчера не знал даже, что это такое, откуда берется и как связана с блокировками — причем так и не понимающего всего этого и сейчас, что только что и продемонстировавшего — в-общем, для абсолютного новичка в теме, не понимающих даже самых базовых вещей, вы слишком неприлично брызгаете слюной. Продолжать, пожалуй, побрезгую, да и бессмысленно.
                                                                                                            +2
                                                                                                            MySQL не добавит тип столбца TEXT, если не задать параметр length

                                                                                                            Тут даже перевод корявый («столбец типа TEXT» был бы логичнее), а в недрах обсуждения выясняется, что проблема в индексировании столбца и неэффективности индекса при обилии префиксов «uploads/-/system/» в значениях (а это уже не хуже).
                                                                                                            С MySQL не получалось эффективно поддерживать вложенные группы

                                                                                                            Опять же, тут боль в эффективности (2,7 секунды заката солнца вручную против 10 миллисекунд через WITH), но про 8-й мускуль знают, но почему-то игнорируют.
                                                                                                            +2
                                                                                                            Объяснение что трудно поддерживать обе БД понимаю, принимаю. Но также и понимаю что при отказе от фишек Postgres можно было бы жить дальше. Вопрос в том, сколько производительности потеряется при этом? 3%? 20%? Мне трудно оценить потерю производительности при использовании Mysql вместо Postgres для GitLab. Хотелось бы увидеть конкретные цифры. Ведь Вы же проводили измерения, правда? Почему же тогда цифр нет в статье?
                                                                                                              +1
                                                                                                              Хотелось бы увидеть конкретные цифры. Ведь Вы же проводили измерения, правда? Почему же тогда цифр нет в статье?

                                                                                                              А с кем вы разговаривете, интересно?

                                                                                                              Original author: Kenny Johnston
                                                                                                                +1

                                                                                                                Цифры есть по количеству пользователей. Если никому не нужна mysql, то зачем его поддерживать, тратить силы и ресурсы?

                                                                                                                  0
                                                                                                                  А где хотя бы эти цифры, по количеству пользователей? Я по ссылке прошёл и не нашёл. Я плохо искал?

                                                                                                                  Вообще Mysql гораздо более распространённая база данных и менее требовательная к ресурсам. То, что у большинства стоит Postgres вызвано тем, что разработчики GitLab давно и настоятельно рекомендуют переходить на Postgres.

                                                                                                                  «В июле 2017 GitLab предупредил, что прекратит поддержку MySQL» — после этого предупреждения всё ещё есть люди на Mysql. Это может значить только одно — Mysql очень сильно востребован.

                                                                                                                  Отказ от Mysql — слабый ход со стороны GitLab
                                                                                                                    0
                                                                                                                    А где хотя бы эти цифры, по количеству пользователей?
                                                                                                                    Вот в статье:
                                                                                                                    Тренд достаточно устойчивый, к примеру в последнее время на 1200 установок с MySQL было порядка 110000 установок на PostgreSQL.
                                                                                                                  +1
                                                                                                                  Смотря что вы вкладываете в понятие «производительность». Конечному пользователю особо и неважно, например, будет git pull происходить 12 секунд, или, например, 15. Процентов потеряли много, но на что они в данном случае влияют? А если никому эти проценты особо не важны, чего бы не сэкономить деньги?
                                                                                                                    0
                                                                                                                    А если никому эти проценты особо не важны, чего бы не сэкономить деньги?

                                                                                                                    Да, вот там прирост по времени 25% потому что не особо важно, и вон там тоже не особо важно было, потому там тоже +30%. А потом сидишь как дурак на компьютере за очень много денег и ждёшь когда очередная программа через дебри экономности продерётся и наконец-то среагирует на клик.


                                                                                                                    Я к чему. Сами по себе 3 секунды может и не много. Но вы правда верите, что только в единственном месте будет такой прирост? Или что он в будущем не станет ещё больше? Или что, как я выше писал, не сложится с аналогичным приростом ещё откуда-нибудь после рефакторинга?

                                                                                                                    0

                                                                                                                    Отказ от фишек постгри (и мускуля тоже :) по сути использование пересечения фишек мускуля и постгри) лишь уменьшит количество ресурсов на поддержку двух баз, поддерживать всё равно надо будет две, кроме фишек есть ещё просто нюансы синтаксиса, или фишки, которые не отключаются

                                                                                                                    0
                                                                                                                    Интересно а в сторону MariaDB смотрели? Там по моим ощущениям с фишками намного проще.