Размышления о транзакциях

Andreika

"PHP for nubies" reader
sverel
А что же Вы будете делать, если всё же в Вашей системе возникнет ситуация когда юзер перевёл бабки не заходя в систему?
%) мы будем обрабатывать вход в систему отдельно от перевода денег.. неужели это не очевидно?

покажите, пожалста, ваш примерный псевдокод(без всяких классов/драйверов и прочего) этих ноубрейн транзакций.. чтоб вы не напрягались, предложу вариант:
PHP:
mysql_query('BEGIN');
if (!$r = mysql_query('UPDATE users SET last_visit_date=1111 WHERE id=1')) {
   die;
}
mysql_query('COMMIT');
так?
 

sverel

Новичок
Нет. Это безсмысленная транзакция.
Я имею ввиду то что ВСЕ запросы должны идти внутри одной транзакции:

PHP:
mysql_query('BEGIN');
mysql_query('UPDATE users SET `balance`=`balance`-1000 WHERE id=1');
mysql_query('UPDATE users SET `balance`=`balance`+1000 WHERE id=2'); // Перевожу бабки от одного к другому
mysql_query('INSERT INTO `transfers_log` (`user_from`, `user_to`, `sum`, `date`) VALUES (1, 2, 1000, 1111)'); 

// А это так называемый "второстепенный" и "не важный" запрос:
mysql_query('UPDATE users SET last_visit_date=1111 WHERE id=1');
mysql_query('COMMIT');
Многим программистам кажется, что в транзакции должны включаться только не разрывные СКЛ-запросы. По этому, многие программисты ставят транзакцию только на первые 3 запроса (ядерная транзакция), а все остальные запросы считают не важными. Как написал pilot выше:
если проходят деньги и есть нормальный коммит - это прекрасно и должно отработать независимо от следующих операций, которые могут быть второстепенными... лучше сразу это понять, имхо
Я же пытаюсь доказать, что второстепенных запросов не бывает и все они являются очень важными. Даже тот который кажется не важным. По этому, в мою транзакцию включен ищё и четвёртый запрос..

В рейльно же CMS/CMF с развитой MVC и прочей структурой выше написанный мною код превращается в одну глобальную транзакцию. Т.е. в начале мы выполняем BEGIN, а в самом конце выполняем COMMIT, и в деструктор пихаем ROLLBACK. Такм образом абсалютно все запросы, на каких бы уровнях они не выполнялись, получатся внутри транзакции. Этим самым мы решим проблему вложенных транзакций и избавимся от понятия "второстепенных" запросов, потому что таких нет - ИМХО.
 

Andreika

"PHP for nubies" reader
окэ.. а теперь напишите все случаи, в которых этот код, по вашему мнению, не переведет деньги..
1. рухнул процесс пхп, сервер или база ушли в даун в момент работы скрипта
2 ...
 

sverel

Новичок
2. Внезапно отключилось эл-ство
3. внутрення ошибка ПО (моего скрипта или PHP, или MySQL или Linux).
4. достигнут time_limit для ПХП
5. много и других, но всего не перечислишь...
 

Andreika

"PHP for nubies" reader
6. затопление помещения
7. ядерны удар по датацентру
8. изъятие серверов мвдшниками
9. нападение марсиан..
омг.. это всё и есть пункт 1 %) фигли фантазировать то..

еще есть варианты, кроме преждевременного завершения работы ?
 

sverel

Новичок
Нет.

-~{}~ 16.09.10 12:45:

Я не понял, тут был какой-то скрытый ответ? Или ответа на мой вопрос пока нет?
 

tz-lom

Продвинутый новичок
Andreika
в базе users нет людей с id=1 или id=2
именно для этого и нужны транзанкции,а не для попадания боеголовки в ДЦ
и кстати нет смысла переполнять транзанкцию лишними данными,каждый запрос может упасть,а не все они жизнено необходимы
 

newARTix

Новичок
sverel
по твоей логике получается, что запросы к системе статистики (допустим для контекстной рекламы) и к системе банковского учета равнозначны? И операцию покупки ценных бумаг, или простую авторизацию стоит прервать из-за ошибки в запросе к ротатору баннеров? Любой тимлид, а далее директор - пошлет тебя с такой логикой.
"Многим программистам" не кажется, оно так и есть. Не надо выдавать желаемое за действительное.

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

sverel

Новичок
newARTix
это не ответ на вопрос: что Вы будете делать, если человек переведёт деньги не заходя в систему (на самом деле он заходил, но у него отвалился "второстепенный" запрос на обновление date_last_visit).
 

newARTix

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

А вообще это странное поле "date_last_visit"... Сдается мне для банковской системы оно вообще лишено смысла. Last logon, и last operation вот логичные поля. А ласт визит это прерогатива попсовых форумов.
 

sverel

Новичок
newARTix
Вы пользуетесь TDD? Если да, то вы должны знать, что если хотя бы 1 из 1000 тестов потерпел феил, то следует считать, что ВСЯ система (проект, программа) не работает!
Если отвалился запрос к статистике, то что-то тут не чисто... и надо разбираться, что именно. Просто так такие простые запросы не отваливаются.
Я же на простом и распространённом примере пытаюсь показать, что один НЕ важный апдейт нарушает логическую целостность данных, хотя сразу это совсем не очевидно.

-~{}~ 17.09.10 00:30:

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

-~{}~ 17.09.10 00:36:

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

newARTix

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

Насчет TDD вообще чушь. Отказ движка БД или отключение электричества в ДЦ, которые ты так полюбил, не входит в область ответственности TDD.

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

sverel

Новичок
Хорошо. Запрос на обновление date_last_visit, как по Вашему, важный или на него можно забить?
 

newARTix

Новичок
sverel
что-то мы прыгаем от Вы на Ты :) Пусть будет Ты.
Все зависит от схемы данных. Где-то оно имеет значение, а где-то не очень и его вообще можно убрать. Где-то может оно вообще завязано через триггеры и процедуры в БД.
 

Raziel[SD]

untitled00
Автор оригинала: sverel
Хорошо. Запрос на обновление date_last_visit, как по Вашему, важный или на него можно забить?
Уже было не однократно сказано, если для твоей системы это важно - значит это важный запрос. Если брать пример об оплате, то важным является оплата, а время последнего визита не имеет особого значения, потому что если не на одной, так на другой "странице" это время будет проставлено.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Картина маслом, блин, спектакль :)

ТС: мне надоело бить маленьким молотком по маленьким гвоздям, я возьму большой и забью все сразу одним ударом!
(хор форума): НЕ ДЕЛАЙ ЭТОГО! Сломаешь часть гвоздей!
ТС: Это в 109 раз быстрее! Я сделаю это!
(хор форума): НЕ ДЕЛАЙ ЭТОГО! Не сможешь проверять, как заходят гвозди!
ТС: Если вы не доверяете своим гвоздям, зачем вам вообще забивать их?!

:)
 

sverel

Новичок
ха-ха. посмеялся :) Но это не совсем уместная аналогия.

Я бы написал так:
- мне надоело забивать каждый гвоздь и постоянно проверять как он забивается. Лучше я возьму спец-молоток которым можно забить сразу все гвозди и он ещё сам проверит каждый гвоздик и если хотя бы один гвоздь не вошёл, то все остальные будут возвращены обратно в коробку как новенькие.
- НЕ ДЕЛАЙ ЭТОГО! Потомучто тогда другие молотки работать не будут. Или скорость будет медленной.
- будут, я проверил и скорость в 109 раз быстрее.
- НЕ ДЕЛАЙ ЭТОГО! Не сможешь проверять, как заходят гвозди!
- а зачем мне проверять каждый гвоздь отдельно, если молоток сам проверяет сразу все гвозди?
- НЕ ДЕЛАЙ ЭТОГО! Пусть лучше важные гвозди останутся, а на второстепенные пофиг.
- как же пофигу? Да шкаф стоять будет и дверцы открываться будут, но если в нём нет полок, то такой шкаф не нужен. А даже если и нужен, то всё равно надо разбираться, почему гвозди не забиваются...
 

akd

dive now, work later
Команда форума
sverel, а можно узнать, ты когда нибудь работал с деньгами? а то много рассуждений о банковских системах, мне интересно есть ли опыт за этой теорией?

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

sverel

Новичок
Нет. с банковскими деньгами не работал, но делал что-то вроде фри-ланс.ру с внутренними деньгми.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
а я работал, и "опыт за теорией" в банках есть
лажа все эти твои рассуждения, sverel, полная
объяснить на конкретном примере, конечно, могу, но ты не настолько приятный собеседник
продолжай спорить - закрою тему с пометкой "ТАК ДЕЛАТЬ НЕ НАДО"
 
Сверху