Как стать автором
Обновить

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

Почему бы тоже самое не реализовать в хранимых процедурах? Мне кажется реализация «логики» в триггерах не самое хорошее решение, хотя может в случае небольшой, по кол-ву таблиц БД, оно и имеет смысл.
«Хранимки» удобная штука, НО не всегда можно через фреймворк работать с ними нормально с учетом AR или еще какой нибудь «прослойки».
Вообще если бы некоторые фреймворки умели разделять таблицы для чтения и таблицы(вью) для записи, то я был бы счастлив.
Я когда-то тоже загонялся подобными счетчиками и пришел к выводу, что хранить этот счетчик в таблице с записью это не очень хорошая мысль. Гораздо проще запихнуть это поле куда нить в мемкеш или в редис (когда я думал об этом был 2007 год и об редиски я ничего не слышал). Если есть данные, то забираем, если нет, то считаем, записываем и показываем… Все просто и не ломает сущности записи всякой ненужной и постоянно изменяющейся метой.
Есть один минус. «Холодный старт» мемкэша или редиса, или что угодно, что наши данные кэширует. Когда на ресурсе под 100 тыс статей а за них проголосовало около 50 тыс людей, то пересчет сумм голосов, показов, комментариев и т.п. становится ооочень проблематичным. Знаю пару сайтов таких, у них при каком либо сбое выработана целая стратегия включения всего.
ну и выборки вида «самые комментируемые» становятся менее удобными
Ну много кого полукилометровые джойны не останавливают. Причина одна: незнание инструментов и неумение ими пользоваться. Это как эникей, который отверткой и канцелярским ножом обжимает кабель.
У триггеров есть огромный недостаток, с лихвой перекрывающий почти все их плюшки, — про триггеры со временем забываешь, их логики нет всегда перед глазами. Особенно плохо, когда триггерами делается что-то не совсем тривиальноею В перспективе это куча проблем на свою голову, особенно, когда в команду приходят новые люди.

А про инкремент счётчиков, хорошие ORM это умеют сами. ActiveRecord::CounterCache
С перспективой проблем нет, так как завершаю любой проект клиенту выдается пакет документации + вики + комментарии в коде.
Вобщем «после меня, да гори оно все синим пламенем» :)
Клиенту сделан сложный инструмент к которому прилагается ооочень подробная инструкция. Мне печально будет, если не читая документации будут на живую что либо ломать, но от дураков защиты нет.
В принципе изготовители машин и т.п. тоже так делают. И есть автослесари которые кувалдой отворачивают гайки, а есть квалифицированные мастера, которые имеют и инструменты и знания и документацию читают :)
НЛО прилетело и опубликовало эту надпись здесь
Прописывайте в договоре, что бы обязывать писать документацию. Порой только так что либо можно заставить делать доки. Хотя отсутствие их у самого разраба в процессе — это или бардак при разработке или уже «привычка» делать как получится. Если бардак, то порой заказчики виноваты в нем, если разрабы не заикнулись про ТЗ более менее полноценное, то это показатель, что НИ КТО не понимает что будет сделано.
Еще, что хуже, они могут переопределять поведение операций. Жесткие баги получаются.
Не страшнее чем простой код или хук в коде, или еще какие нить удобные варианты (валидация, пре и пост обработка данных)
Я бы использовал хранимки. Они не страшнее. Суть в том, что тригеры могут неявно переопределить поведение операции. Вы что-то инсертите в таблицу, а инсерт не все поля вставляет. И еще много чего может делать.

Тригеры использую, если код легаси и если уже так повелось, что при меньших затратах, можно на них что-то сделать. Логирование или кеширование.
Обычно в среднем проекте все что можно перенести на сторону sql сервера — переносим.

Поддерживать потом не устаете? Триггеры — это одна из наименее очевидных вещей в БД, особенно при отслеживании «что сломалось».
3 привила:
1. написал — тестируй
2. не делать «на живую»
3. выносить в sql минимальную логику

Я сторонник того, что бы грамотно проектировать системы с учетом хотелок в будущем + всю логику делать максимально простой и минималистичной.

К тому же документацию ни кто не отменял.
Третье правило противоречит подходу «все что можно перенести на сторону sql сервера — переносим».

К тому же документацию ни кто не отменял.

Документация устаревает мгновенно.
Добавьте 4 правило, за невыполнение которого нужно бить по рукам:
4. Написал/изменил код — задокументируй. Если не задокументировано, то тестерам непонятно что тестить — отбирай печеньки у программиста. Не задокументировано тестировщиками — лишить печенек их.

Четкая структура и правила… и опять же рас%;;%во не имеет отношения к триггерам.

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

Мы же не про интернет-магазины говорим, а про что-то большое и серьезное?
Вообще, стоимость разработки _кода_ это чуть ли не самая мелкая статья затрат. Основной бюджет съедает покупка софта/железа и проектирование. На кодирование должно отводиться, если не ошибаюсь, не более 20% времени. К моменту начала кодирования должны быть проработаны и задокументированы все структуры, модули и API.
К моменту начала кодирования должны быть проработаны и задокументированы все структуры, модули и API.

Не взлетит. К моменту начала кодирования и в его процессе требования стопицот раз поменяются/уточнятся.
Да какие проблемы: за ваши деньги — любой каприз :)
А если серьёзно, то именно это и должно заставлять нормально документировать систему. Я лично не могу удержать все связи проекта в голове и никогда не дам гарантию, что изменив модуль А мы не поимеем проблемы в модуле Д, причём, опосредованно через модули Б и В. Нужна дока, обязательно.
В том-то и дело, что дока не поможет, потому что никто не будет успевать ее обновлять.

Поэтому:
— изолированное тестирование
— функциональное тестирование
— отслеживание зависимостей с помощью специальных средств
— соблюдение контрактов и LSP
С другой стороны, что такое тесты, как не формализованное описание требований из доки? Тесты же вы успеваете обновлять?
Тесты описывают поведение на уровне контракта (если это unit-тесты) или бизнес-сценария (если функциональные). Это те места, которые меняются реже других.

И да, изменение тестов — это дешевле, чем изменение документации и тестов.
Что в итоге отдаётся заказчику? Неужели набор тестов?
На счёт цены, конечно, соглашусь.
Заказчику отдается система, очевидно.
Поставим вопрос по другому: нужна ли заказчику система в виде чёрного ящика? Т.е. примет ли он её?
Как не странно, но в 99% случаев «черный ящик» принимается (любая покупка ПО). Мало кто из заказчиков понимает вообще зачем им 3 копии по 1200 страниц некой документации + электронная вики.
Зависит от условий контракта. Но в любом случае написать документацию на систему на момент ее сдачи проще, чем постоянно поддерживать актуальную документацию в процессе разработки.
70% документации нужно и самим разрабам, остальное в процессе, так как описываются «детали».
Любое изменение в коде — это работа программиста за которую нужно платить:
1. нужна причина
2. нужно обоснование
3. почему начальный код написан не верно
4. нужно описание «как оно на самом деле должно быть»

т.е. переделки кода в любом случае проходят через ведущего разраба и тех. писателя
Вы почему-то не замечаете разницы между документацией на код и документацией на задачу. Хотя это разные вещи.
Я сливаю эти два понятия. Т.е. мыслю не листами бумаги, а перекрестными ссылками и метатегами.
А зря. Это два совершенно разных массива информации (хотя они и связаны ссылками). Но порядок возникновения у них весьма конкретный.
Можно тогда отделить еще и «технические» ТЗ и т.п. вещи, но порой смысла в этом нет.
У каждой фирмы свои методологии разработки.
О, да, есть еще менеджер, который следит за сроками и затратами денег. Как раз он орет на ведущего разраба за переделки.
Одно дело — документация верхнего уровня (ER, слои, инфраструктура). Она нужна, конечно. И меняется медленно.

Совсем другое дело — документировать каждый класс, функцию, триггер и так далее.
Не, я совсем не призываю документировать всё подряд до самой мелочи. Сам в этом случае ограничиваюсь небольшим описанием подпрограммы и общими комментариями по коду, чтобы можно было понять суть, просто пролистывая его. Ну и в местах, где пришлось подумать, записываю причину выбора именно такого варианта, чтоб самому потом дважды не думать «зачем так, можно же по другому?»
Расписывать все до мелочи — есть свой плюс:
Когда другой человек в него полезет, то ему будет понятно ВСЕ без чтения пары страниц документации.
Например в ходе работы в какой нить системой выяснилось, что контроллер глючит, если приходят пакеты не по 8 байт, а если первый байт равен 0, то что бы пакет был более 12 байт.
Это лучше написать в коде (в вики дубль), так как если что нужно поменять по мелочи, то лучше видеть эти данные, чем «лопатить» раздел «особенности».
Вы считаете, что документация на протокол передачи данных (который, конечно же, должен быть полностью документирован) и документация на код — это одно и то же?
Я считаю что нужно разумно подходить как к документированию, так и к коду.
Если целесообразно какие то комментарии выносить в код, то это делается.
Более полная инфа есть в документации, но не всегда целесообразно не потратить пару минут времени на пару строк в коде, а заставлять программиста, которому надо поменять пару строк кода, читать 100 страниц доков.
Есть информация, которая касается архитектуры приложения, а есть локальная.
Да, от себя добавлю, что в идеале программисту на руки в тикет системе должно попадать нечто вроде:

protected function beforeDelete()
{

/*
ссылка на документацию что надо сделать
ссылка на описание нужных данных в БД
ответственный за подсистему из архитекторов
*/
}

В идеале — да.
Извините, оборвалось.

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

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

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

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

Каждый исполнитель-программист знает свою скорость в поинтах, сколько он может успеть сделать за месяц=сколько он может заработать.
Менеджер проекта понимает общую скорость работы, процент выполнения проекта, легко нанимает людей и подключает к процессу.
Программеры пишут код когда им хочется, а не с 9 до 18.
Профи программеры пишут код «запоями» и помногу, от этого имеют большую зарплату.
Они выдают шаблон приложения/системы.

На основании чего?
На основании всего (неправильный вопрос).
Есть хотелка клиента по системе, есть общая архитектура, есть проработанный план что и как будет делаться, есть документация — начинать делать основу уже можно: наметить модули, функционал, описать данные передаваемые и т.п…
Чтобы был проработанный план, надо собрать требования. А собрать до начала разработки требования в таком объеме, чтобы можно было запроектировать все, включая API, не удается.
Кому не удается?
Пока не готово ТЗ ни одной строки кода не появится.
Переписывать код в процессе по причине «а, я вот еще у конкурента подсмотрел» — это недоработка разработчиков системы на начальном этапе.
Если мы говорим про сложные системы, например учет энергопотребителей, платежные системы и т.п., но пока не будет все проработано до мелочей трогать код вообще не имеет смысла (только для организации тестов чего либо)
Кому не удается?

Аналитикам/РП. Повторюсь, я вот за десять лет такого ни разу не видел.

То есть несомненно, «пока не готово ТЗ, ни одной строки кода». Но как только ТЗ попадет к разработчику, сразу выяснится, что в нем есть миллион и одна ошибка.
У Вас ТЗ — это просто куча текста или собраный прототип или что?
Текст + набор диаграмм.
А прототипы системы собираете?? UML?
UML — по необходимости.
Прототипы — смотря что под ними понимать.
Требования — это совокупность текста и картинок в первую очередь.
Главное не забыть еще раздел с общим текстом «нафига оно нам нужно». По практике иногда выходит так, что заказчику после прочтения данного раздела показывается более простое элегантное решение, чем он напридумывал. Часто предварительное ТЗ представляет собой нечто весьма забавное, как копипаст из умных статей собранный в одном месте.
Вот тут соглашусь.
Вообще-то, это первый и основной раздел требований, business objective.
Заказчики разные, и требования «хочу что бы было все зае%;№» — порой встречаются (хорошо, что все рже и реже). :)
Написал/изменил код — задокументируй.

«Не взлетит». В том смысле, что никто не будет выполнять. У Хамбла/Фарли это описано в Continuous Delivery. Лучшая документация — это сам код.

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

А это банально неверно, потому что тестировщики тестируют по бизнес-кейсам, а не по программистской документации.
Лучшая документация — это сам код.
и
тестировщики тестируют по бизнес-кейсам
=
если тестировщики тестируют не по программерской документации то для них всё ж таки придётся писать отдельное описание кейсов для тестирования и «лучшая документация — это сам код» никак не прокатит.
А что ВНЕЗАПНО пишут аналитики?
для них всё ж таки придётся писать отдельное описание кейсов для тестирования

Не так. Тесткейсы тестировщики пишут сами. По требованиям. Которые пишут аналитики.
Не задокументировал = задача не выполнена = на заплачено.
Осталось найти людей, которые будут работать на таких условиях.
Легко… Только они это… Триггеры по 1000 строк писать будут.
Ммммм, ну да, проще найти 10 говнокодеров, которые нагадили и забыли. :)
Профи нужны.
И опять же повторюсь, документированием занимается тех. писатель по факту принятия кода (в паре с разрабом), код пишут кодеры. Кодет не модет получить задачу без формулирования её разрабом, он де принимает код (если нужно, то отправляет на тестирование) и тех. писатель тут же вносит правки в документацию.
Ни кто не насилует бедных кодеров.
Если уровень программиста и умение его читать доки позволяют, то можно в sql вынести все, но, что бы быть готовным к обслуживанию «эникеем» или «веб-мастером» делаются минимальные задачи. В принципе это не значит, что программист поддержки достаточно профессионален что бы читать чужой код и понимать его смысл.
Поделитесь, пожалуйста, как вы версионируете код триггеров и хранимок.
точно также как текстовые файлы с кодом на C++ или Java.
И никогда никаких проблем с обновлением боевых баз?
А вот тут давайте подветку сделаем «а как Вы обновляете боевые базы?»
Давайте ;) Я внимательно слушаю ;)
так к вам вопрос-то. В C++/Java текст программ компилируется в бинарный код и выкладывается в определённое место как часть продукта или готовый продукт.

С базами данных у вас не так?
Я раньше его задал ;)

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

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

А вот это неправда. В типичном энтерпрайзе базы меняются регулярно.
Изменение боевых баз — это нетипичная ситуация.

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

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

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

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

(в отличие от программного кода, который можно просто заменить)
в любой системе есть данные которые необходимо сохранять при обновлении системы.
В бинарном коде, о котором вы спрашиваете выше, их нет.
ну так в тексте триггера тоже данных нет. Это просто код который выполняется при определённых условиях. Равно как и скрипт на PHP или скомпилированный C#.
Но триггер привязан к БД, в которой эти данные есть. Обновить триггер, не обновляя БД — можно, но в реальности эта задача всегда оказывается не такой тривиальной, как кажется.
Еще больше проблем когда нудна определенная последовательность обновления структуры таблиц и триггеров. В принципе как и кода.
Триггеры — это точно такой же код.
код тоже привязан к данным. Нельзя же взять и поменять (в простейшем случае) имя таблицы с orders на workorders но оставить без изменений код. Равно как и наоборот нельзя.
Имя таблицы — не данные.
Имя таблицы — это такие же данные. Код привязан к этим данным.
Имя таблицы — не данные, а структура. Тот же код. Данные — это то, что в ней лежит (и необходимо сохранить для работы пользователей).
Да́нные (калька от англ. data) — представление фактов и идей в формализованном виде, пригодном для передачи и обработки в некотором информационном процессе.

Имя таблицы — это данные о том как именуется данная группа данных о неких объектах.

Так же как структура таблицы — это тоже данные.

Мы с вами говорим о разных «данных». Я — о тех (и только о тех), которые интересуют бизнес и нужны для достижения бизнес-цели.
тогда какие проблемы? Лежат данные и пусть лежат. Чё их менять-то?

8)

Если поменялись безнес-правила, например раньше поле ИНН было обязательным а стало обязательным — вот тут при обновлении может понадобиться изощрённая логика.

Хоть в триггере это делай, хоть в процедуре, хоть в коде на Ruby.
Задача в том, чтобы при изменении структуры/бизнес-логики в БД данные, с которыми работают пользователи, не продолбались.

И это не всегда тривиально.
Хоть «девочкам из бухгалтерии» инструкцию пиши.
Есть как дампы БД, так и версии в вики.
К сожалению чего либо вроде GitSQL пока не найдено.
И как вы ваши дампы деплоите?
> Обычно в среднем проекте все что можно перенести на сторону sql сервера — переносим.

Ужас какой. И никаких проблем еще не было?
А если нужно сменить тип базы данных?
Что на что меняем? А если меняем, то сначала меняем, а потом разгребаем что вышло или читаем документацию, думаем, меняем на тестовой машине, проверяем/тестируем, переносим на продакшен.
Невнимательность и криворукость может быть везде. Не в триггерах дело.
Если нужно сменить тип БД, значит у проектировщиков надо отобрать их зарплату, ибо раньше думать надо было. А использовать любую из более-менее продвинутых СУБД просто как хранилище — это совсем не комильфо. В этом случае всё что надо, это mysql 3.23
Тогда уж «все что нужно, это sqllite или data.txt» :)
Мне кажется, что многие боятся триггеров, хранимок или вьюх по-тому, что мало с ними работали и в голове нет «чеклиста» с пунктом «глянь триггеры, вьюхи, хранимки». Когда доделываешь 10-20 проект в котором что хранимки, что триггеры бывают по 1000 строк, то к этому момент времени и ответственности больше и опыта и понимания, что даже конфиг nginx может быть сооовсем непростым.
что триггеры бывают по 1000 строк

Это феерично. Не знаю даже что написать. К Макконнелу — лечится!
ОМГ… Выкиньте вы эти триггеры на 1000 строк. У вас там что, лапша из
if product_id = 1 then discount_pcnt = 5
if product_id = 2 then discount_pcnt = 3
...
if product_id = 100500 then discount_pcnt = 10

?

Переведите в нормальный вид, пожалуйста…
Извиняюсь, промазал.
Лично я их боюсь избегаю потому что нет удобных инструментов разработки, тестирования, отладки, версионирования и т. п.
С версионностью — костыли в виде вики.
Для разработки есть инструментарий достаточно удобный, тестировать/отладка — не проблема вообще при мелких тригерах (счетчики, изменение данных по мелочи). При больших триггерах помогают схемы на листах бумаги «где что меняется». При сложных структурах получаются более сложные схемы, но не сложнее чем разработка архитектуры приложения.

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

Охохохо… Вот, например, задача о том, как эффективно раскидать значения по регистрам/хипу/стеку — NP-полная. Современный компилятор ее решает заведомо лучше.

Это, конечно, не в тему статьи, а так — про мифы и неверные аналогии.
Может и стореды тогда не использовать — вдруг новый тип базы не будет их поддерживать.?
Никогда не делайте логику на триггерах, кроме каких-нибудь совсем элементарных вещей. Замучаетесь потом проблемы разгребать. Была у меня одна немаленькая система, целиком построенная на триггерах. Это адЪ. Особенно весело ловить ошибку «таблица мутировала», когда она возникает в результате цепочки из нескольких триггеров, которые «вызывают» друг друга.
Да, это всё решаемо, но поверьте вышеотписавшимся — не пихайте бизнес-логику в триггеры.
В чем проектировалась БД и как отслеживали причину сбоя?
На все типовые операции у меня были полуавтоматические тесты с очень подробным логгированием. Так что отследить ошибку было довольно просто. Другое дело, что раздражало это всё очень.
Нормальная практика автотестов. А раздражение от сбоев — это особенности профессии.
Как раз нет. Раздражение было именно из-за архитектуры системы.
Не проработанная архитектура которая кучу раз переписывалась?
Я согласен с некоторыми Вашими высказываниями в комментариях, но по теме топика мы не сойдёмся никогда. И именно потому, что архитектура, целиком построенная на триггерах, не может быть стройной. Просто в силу природы триггеров. Да, она может быть рабочей, но только ценой большой черезжопицы. По-моему, Ваши триггеры по 1000 строк это доказывают.
а десяток модулей по 1000 строк использующий ORM и выполняющий точно такую же функцию что доказывает?
Не могу ответить,.т.к. не люблю ОРМ
Целиком строить на триггерах так же глупо как и целиком строить на коде.
К сожалению пример с 1000 строками малость сбил с правильных мыслей, но поверьте мне, все 1000 строк триггера или хранимки придуманы и написаны не одним человеком, а группой специалистов которые разобрали все плюсы и минусы и понимают всю долю ответственности за свое решение.
статья хорошая, примеры наглядные но можно бы рассмотреть более однозначную задачу. Например историю изменений — поменял кто-то данные и триггер сам вставил в таблицу пометку кто и когда правил. Это будет делаться независимо ни от внешних программ, что недостижимо другими средствами.

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

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

Я в курсе. Но информации о том, какой именно пользователь работает в приложении (независимо от внешних программ, как вы сам написали), в нем нет.
есть.

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

Дурное дело нехитрое.
Не из-под админского, а из-под серверного.

А вы как предлагаете? Заводить в SQL пользователя на каждого пользователя системы? А если их двадцать миллионов? И при этом как — для каждого пользователя строить свое подключение к БД на основании его данных? И как? Пароль для подключения откуда возьмем? У пользователя спросим? Или будем доменный эккаунт имперсонировать на сервере?

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

SQL-сервер предоставляет кучу средств для всего. Можно конечно это всё выбросить и написать собственные костыли. Но зачем тогда SQL-сервер?
Вообще, создание сессии в СУБД — это довольно накладная операция. В случае с вебом стопицот пользователей и постоянный переконнект дадут слишком большую нагрузку. Здесь действительно дешевле держать пул соединений от одного «системного» пользователя и иметь свой слой аутентификации/авторизации.
А почему нет?

Например, потому что некоторые SQL-сервера начинают падать тысячах так на пятнадцати-двадцати пользователей.

Где тогда хранить эти двадцать миллионов пользователей?

Например, в AD. Или в таблице.

SQL-сервер предоставляет кучу средств для всего.

Надо только очень хорошо осознавать границы их применимости.

Вы попробуйте ответить на вопросы в комменте выше.
отвечаю, хехе

— если даже SQL-сервер падает на 15 тысячах пользователей и другое вполне себе упадёт

— современные SQL-сервера вполне себе интегрируются с Active Directory и аутентифицируют с её помощью (а если пользователей хранить в таблице то никаких проблем брать из этой таблицы пользователя триггером, т.е. про недоступность логина это лукавство)

— по границам применимости — именно! За Oracle платят сотни тысяч не потому что он такой красивый а потому что использование его возможностей значительно сокращает сроки разработки и удешевляет поддержку.
если даже SQL-сервер падает на 15 тысячах пользователей и другое вполне себе упадёт

Удивительно, но не падает. Вот удивительно. Но не падает.

современные SQL-сервера вполне себе интегрируются с Active Directory и аутентифицируют с её помощью

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

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

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

Уже или признайтесь, что вы этого в таких масштабах не делали, или расскажите, как делали.
Если возможно, то из вставляемых данных. Части в запросе есть Id пользователя совершающего действие: пользователь создал запись в блоге, добавил картинку, написал комментарий и т.п.
А если невозможно (данные не содержат прямого указания на пользователя)?
Ну я не могу заставить sql прочитать сессию, по ней сделать запрос на них пользователя и сохранить его в лог… или могу :)
Не можете.

Отсюда мораль: нельзя сделать историю изменению только на стороне сервера БД, не меняя код приложения.
Вот, например, что знает о пользователе оракл: docs.oracle.com/cd/E14072_01/server.112/e10820/dynviews_3016.htm
OSUSER 		VARCHAR2(30) 	Operating system client user name
PROCESS 	VARCHAR2(24) 	Operating system client process ID
MACHINE 	VARCHAR2(64) 	Operating system machine name
PORT 		NUMBER 		Client port number
TERMINAL 	VARCHAR2(30) 	Operating system terminal name
PROGRAM 	VARCHAR2(48) 	Operating system program name
TYPE 		VARCHAR2(10) 	Session type
Если к ораклу обращается один и тот же демон, то пользы от этих данных почти ни каких.
Это оракл знает о том, кто к нему обращается. Теперь представьте, что к нему обращается веб-сервер. Много пользы вам от этих переменных будет?
От этих — нисколько. Я всё-таки повторю вопрос, который задал ниже: «На уровне приложения он же как-то аутентифицируется?» Что-то же мы знаем об этом пользователе, хоть ИПшку? Не важно на каком уровне: БД или приложения.
Если знаем, и всё ещё продолжаем говорить на примере оракла, то в нём есть очень удобная вещь: контексты (типа переменных окружения), которые вполне позволяют обойтись одним кодом для различных вариантов подключения.
Не важно на каком уровне: БД или приложения.

Важно. Потому что если мы знаем это только на уровне приложения, логировать в БД мы это не можем.

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

Да они много где есть, только их должно заполнять приложение. Что возвращает нас к тому, что приложение должно предпринять некоторые действия для того, чтобы работал якобы универсальный код на стороне БД.
Ну конечно должно! Про универсальность я имел в виду именно то, что написал: «один [субдшный] код для различных вариантов подключения». Варианты подключения: толстый клиент, внутриСУБДшные процессы, веб. В случае с вебом, естественно, сервер приложений должен предоставить базе некоторую свою информацию.

Если же речь про то, что всё это не надёжно, сервер приложений можно поломать, сессию можно увести, так ведь и пароль честного субдшного пользователя можно подсмотреть…

PS: Перечитал ветку, напоминает разговор после 150 коньяка: все всё понимают, со всем согласны, но продолжают спорить, потому что «хорошо сидим».
Так вот, топикстартер утверждал, что «это будет делаться независимо ни от внешних программ».

Я, как бы, часто слышу такую аргументацию за подход с триггерами для логирования, но в реальности еще ни разу это не работало.
Кто, когда, откуда и чем: это СУБД знает отлично.
Это в том случае, если у вас пользователь напрямую в БД обращается. А если туда лезет appserver/webserver/вебсервис/нужное вписать — БД про пользователя больше ничего и не знает.
На уровне приложения он же как-то аутентифицируется? Или я уже туплю и не понял сути разговора?
На уровне приложения он (пользователь) аутентифицируется. Но это информация приложения, ее нельзя прозрачно и независимо от приложения получить на сервере БД и записать в лог доступа.
Приложение обязано сообщить эту информацию СУБД перед началом своих тёмных делишек.
После этого утверждения фраза о том, что «Это будет делаться независимо ни от внешних программ» можно выкинуть в утиль. О чем, собственно, изначально и был спор.
Есть АПИ, есть определённые предварительные процедуры, которые должен выполнить клиент (не важно какой). Без этого он не получит своих долгожданных данных. Вопрос про аутентичность самого клиента, я надеюсь, в рамках этой ветки не рассматривается.
Если клиент должен что-то сделать, то уже нет никакой независимости от клиента. Я именно это пытаюсь продемонстрировать.
Недавно хотел сделать что-то подобное на триггерах, правда на innodb.
Но потом отказался, когда выяснилось, что в mysql триггеры на каскадном удалении не срабатывают.
Сделал на хранимках.
Триггеры в таком применении, для улучшения производительности плохи тем, что срабатывают каждый раз, особенно если речь об myisam, где лочится таблица, а не строка.
Обычно для решения этой же проблемы делаем
или а) по крону апдейтим счетчики в основной таблице, по крону, а не по триггерам, т.к. крон проще контроллировать и запускать раз на 10 комментариев например, а не на каждый.
или б) для счетчиков выделяется полностью отдельная таблица, занимающая мало места, только ид*нум_комментс*_нум_виевз, без всяких текстовых и прочих лишних полей.
или в) комментарии из таблицы комментариев пишутся так же в таблицу без комментариев такой же структуры. одним запросом больше при записи, но зато кол-во комментариев выгребать в случае чего намного быстрее и проще можно.
Раз в минуту запускать крон — это не проблема.
Проблема в том, что опять же, мы выполняем хз какой код (чаще всего интерпретируемый), делаем выборки, прокачиваем данные из БД в приложение (слава богу если там их немного и сеть/число коннектов позволяет), вычисляем суммы или апдейтим данные… опять же ждать минуту пока данные обновятся — не всегда приемлемо.
Отдельные таблицы — это далее получаем доп запросы или джойны. Чем больше данных, и чем меньше память сервера тем больше желание сделать все более быстрее.
Тип таблицы — это «дело наживное». Какой быстрее работает, такой и будет.
Лишние запросы — это ЛИШНИЕ запросы. В случае с посещаемостью небольшой проблем не вижу, в случае с высокими нагрузками можно и на счет кэширующих систем холивор развести.
прокачиваем данные из БД в приложение
Не обязательно. Даже если забыть о хранимках, то update select никто не отменял.

Отдельные таблицы — это далее получаем доп запросы или джойны. Чем больше данных, и чем меньше память сервера тем больше желание сделать все более быстрее.
Именно — быстрее.
Если Вы выносите кол-во комментов и просмотров (часто обновляющуюся информацию) из таблицы новостей (редко обновляющуяся информация), то таблица новостей (огромного размера) перестает у Вас дергаться с дикой частотой (особенно если Вы просмотры логируете), а дергаться начинает мелкая таблица (со страшной скоростью, в меру ее размера), как следствие ускоряется и апдейт и сортировка и выборка… особенно по кол-ву комментариев/просмотров.

Тип таблицы — это «дело наживное». Какой быстрее работает, такой и будет.
Разница в типах локов таблиц это наживное дело?

Лишние запросы — это ЛИШНИЕ запросы.
А быстрые запросы — это БЫСТРЫЕ запросы. Вчера были маленькие но по 2, а сегодня большие но по 5:)

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

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

На одной чаше весов дергать 2 таблицы при показе статьи/ленты статей, на другой дергать всего 1 таблицу… хм… если вывод статей в приоритете, то второй вариант. Если нам надо часто считать статистику, то первый.

Просто часто обновляемые данные выносятся в отдельный блок для более быстрой с ними работы
Если статистику выбираем часто, то да, соглашусь.
Речь идет о том, что мы должны быстро отдавать контент с максимальной скоростью… да и в принципе триггеры — это удобно и меня использование их не парит более чем пара строк на каком нить языке. Если я могу сделать так, что при отключении света у меня аварийная подсветка загоралась, я сделаю это. Бегать в темноте за свечками или хранить по фонарику в каждой комнате — это не для меня.
статистику и в гугле/метрике посмотрю,
То есть Вам нравится идея еще более кардинального выноса статистики:) Вы не согласны только с половинчатым решением?:)

На одной чаше весов дергать 2 таблицы при показе статьи/ленты статей, на другой дергать всего 1 таблицу… хм… если вывод статей в приоритете, то второй вариант. Если нам надо часто считать статистику, то первый.
Но плечи у этих весов разные.

Речь идет о том, что мы должны быстро отдавать контент с максимальной скоростью…
Именно поэтому и предлагаем как альтернативу — работу с небольшими объемами данными для скорости.
Нужно отдавать страницу С рейтингом и числом комментариев. В данном случае одна таблица целесообразнее.
Разница в типах локов таблиц это наживное дело?
Как надо так и делается. Разные типы таблиц имеют разные плюсы и минусы.
OMG! Про то как это поддерживать уже озеро слёз налили выше. Я добавлю еще: а какая прелесть это отлаживать!.. Неведомая лажа из-за того, что что-то кто-то изменил и ВНЕЗАПНО сработал забытый триггер, который вызывает хранимку, побочным эффектом которой запуск другого триггера и так дальше по цепочке подарит самые незабываемые впечатления любому разработчику.

>>все что можно перенести на сторону sql сервера — переносим.

А уж как подходит SQL для бизнес логики — это сказка.

Брррр…

Внезапно тригеры не возникают. Всего 3 события + не стоит городить много тригеров, а лучше объединять. Ну и на все есть инструментарий по проектированию, документация, блок-схемы. Согласен, что когда триггеров много, то если сразу лезть в код, то можно схватить проблем.
>>Согласен, что когда триггеров много, то если сразу лезть в код, то можно схватить проблем.

Угу. О чём и речь. «Не лезь в код, можно схватить проблем» — прекрасная характеристика подобного подхода.
Речь о том, что если показали как молотков гвоздь забить, то всю жизнь и забивают, а о том, что есть шурупы, клей и т.п. не в курсе или боятся использовать «а вдруг я пальцы склею».
не стоит городить много тригеров, а лучше объединять

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

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

SRP плачет.

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

Вот именно поэтому и стараются всю логику переносить в сторону платформ, где такие инструменты есть.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории