Использование MySQL триггеров или транзакций?

8

Я хочу спросить ваше мнение об использовании MySQL триггеров или транзакций на веб-сайте.

На самом деле у меня есть paymentтаблица истории с - UserId | OperationId | Comment | Credits | Sign (debit or credit). Таким образом, каждая платежная операция вставлена ​​в эту таблицу.

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

Здесь проблема. Как я могу быть уверен, что общая сумма кредита из profileтаблицы будет синхронизирована с операциями из paymentтаблицы истории?

Я думал, используя 2 метода:

  • MySQL триггеры или
  • транзакции, закодированные в исходном коде

Что является более надежным? Что если у меня большая база данных (более 100 000 пользователей)?

Есть ли у вас какие-либо предложения для этого?

Движок BD MySQL - это InnoDB.

Эк Космос
источник

Ответы:

8

Без сомнения, я бы исключил триггеры и строго придерживался транзакций.

Триггеры по своей природе являются хранимыми процедурами. Их действия практически трудно откатить . Даже если все базовые таблицы являются InnoDB, вы будете испытывать пропорциональный объем общих блокировок строк и раздражающую прерывистость от исключительных блокировок строк. Так было бы, если бы триггеры манипулировали таблицами со стагнацией INSERT и UPDATE для выполнения MVCC в тяжелых условиях внутри каждого вызова триггера .

Добавьте к этому тот факт, что надлежащие протоколы проверки данных не реализованы в языке хранимых процедур MySQL . Бизнес-аналитика в порядке, если она содержится в базе данных, при условии, что язык хранимых процедур может обрабатывать транзакционную среду . Как администратор базы данных MySQL, я должен честно сказать, что с MySQL это не так. Oracle (PL / SQL), PostgreSQL (PL / pgSQL) и SQL Server (T-SQL) имеют это преимущество над MySQL.

Что касается транзакций, MySQL имеет InnoDB в качестве основного ACID-совместимого механизма хранения (механизм хранения Deafult в MySQL 5.5). Он имеет отличное восстановление после сбоев и соответствует протоколам соответствия ACID.

Я бы предпочел трансакиты триггерам каждый раз.

RolandoMySQLDBA
источник
3

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

Конечно, масштабирование до 100 000 пользователей зависит от вашего приложения и трафика базы данных, который оно генерирует. С MySQL под большой транзакционной записывающей нагрузкой вы можете вскоре столкнуться с бременем разделения и / или репликации вашего набора данных для поддержания приемлемого ответа приложения.

Тем не менее, существуют альтернативы шардингу MySQL. Одним из них является Clustrix (мой работодатель), который представляет собой масштабируемую параллельную высокопроизводительную систему баз данных SQL для одного экземпляра. Это кластерная система баз данных, которая представляет собой один сервер MySQL. Безболезненное масштабирование базы данных, описанной в этом потоке, до 100 000 пользователей в одном экземпляре Clustrix не потребует никакого шардинга и дополнительной логики приложения.

blbryant
источник
+1 за хороший ответ и бесстыдная заглушка для Clustrix. ЛОЛ !!!
RolandoMySQLDBA
1

Хороший ответ от Роландо.

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

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

Кроме того - вам не нужно иметь всю логику в части бизнес-логики кода - вам может потребоваться обеспечить целостность таблицы с помощью хранимых процедур. Это может запустить транзакцию, выполнить несколько обновлений и заставить все откатиться, если что-то не получится. Таким образом, кто-то, глядя на базу данных, может видеть логику для вставки заказа, например. В современном мире это менее важно, поскольку веб-службы могут быть единственным интерфейсом доступа к БД; но в случае, когда несколько исполняемых файлов имеют доступ к БД, это может быть огромным.

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

По сути, между регулярно запланированным заданием cron (или заданием агента базы данных) и хорошими хранимыми процедурами вы можете выполнить 99% того, что вам нужно. 1%; переосмыслить проект.

Жерар ОНЕЙЛ
источник
В заключение, ваш совет однозначно НИКОГДА НЕ ИСПОЛЬЗОВАТЬ ТРИГГЕРА в серьезном приложении с бизнес-логикой?
Ифеди Оконкво,
В общем да. Я вижу ситуации, когда у вас есть триггеры для выполнения странных, возможно, многорядных, проверок. Я также вижу, как они используются для генерации флагов фактов - возможно, это просто форма проверки, где результат проверки где-то хранится. Я вижу, как они используются для обновления информации о таблице (например, флаг или таблица, которая указывает, какие строки были изменены). Однако, независимо от того, насколько просты и понятны эти реализации, я бы предпочел, чтобы это делалось в хранимой процедуре или в API-интерфейсе db (т. Е. В модели).
Джерард ONeill