Транзакция и нетранзакционное действие.

Givv

Привет, может не тот форум, но вопрос примерно такой:Как работать с ситуацией когда надо совместить запись в БД и какое-нибудь внешнее действие, типа отправки емайла.Простой сценарий:1. В таблицу вставляется запись с флагом Sent=02. По этой записи каким-то образом генерируется и отправляется емайл.3. В записи устанавливается флаг Sent=1Если коммитить после #1, то возможна ситуация когда емайл отправится, а Sent останется равным 0.Если коммитить после #3, то возможна ситуация когда емайл отправится, а записи в таблице не будет вообще.PS: В общем случае имеется ввиду не только отправка emailа, но любое действие типа вызова вебсервиса или записи чего-нибудь в оборудовние.
24 ответа

Givv

В любом случае не надо делать такие вещи, как отправка email внутри транзакции.
Если коммитить после #1, то возможна ситуация когда емайл отправится, а Sent останется равным 0.
это еще почему?


Givv

Shocker.Pro,Ну сеть упадет между #2 и #3 или еще что-то.


Givv

Привет, может не тот форум, но вопрос примерно такой:Как работать с ситуацией когда надо совместить запись в БД и какое-нибудь внешнее действие, типа отправки емайла.Простой сценарий:1. В таблицу вставляется запись с флагом Sent=02. По этой записи каким-то образом генерируется и отправляется емайл.3. В записи устанавливается флаг Sent=1Если коммитить после #1, то возможна ситуация когда емайл отправится, а Sent останется равным 0.Если коммитить после #3, то возможна ситуация когда емайл отправится, а записи в таблице не будет вообще.PS: В общем случае имеется ввиду не только отправка emailа, но любое действие типа вызова вебсервиса или записи чего-нибудь в оборудовние.
1,коммит, 2, 3, коммит Но в любом случае придется врукопашную изображать из себя двухступенчатую транзакцию, и возможны коллизии.


Givv

Givv,Длительные внешние процессы делать асинхронно. Есть распределенные транзакции, но письма к ним не относятся.Просто отправку повесь на JOB субд или IIS.


Givv

ИМХО для начала стоит определиться с тем, какое поведение требуется.1. Добавить запись о начале отправки;2. Отправить письмо;3. Изменить статус на Отправлено.Если письмо не отправилось то повторить попытку.Если попало в gray list, то повторить попытку.Если...А потом уже выбирать решение.Мне пока не понятно, при чём тут транзакции.


Givv

Ну сеть упадет между #2 и #3 или еще что-то.
Сеть между чем и чем?Пусть "отправлятор" ставит в очередь сообщение о том, что отправил, а "разгребатор" этой очереди как сеть будет, то выгребет сообщение из очереди и изменит статус в БД.


Givv

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


Givv

skyANA,Основной вопрос в том, что делать, если письмо отправилось и выключилось электричество.Есть ли общепринятая практика разруливания таких ситуаций?
Развить обсуждение на форуме об этом страниц на 20


Givv

Givv,Вы представляете, что происходит с обычной транзакцией, когда выключается электричество?


Givv

skyANA,Основной вопрос в том, что делать, если письмо отправилось и выключилось электричество.Есть ли общепринятая практика разруливания таких ситуаций?
ИБП.Что делать, если на сервер упадет метеорит, или начнется зомби-апокалипсис - не знаю.


Givv

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


Givv

Givv,Вы представляете, что происходит с обычной транзакцией, когда выключается электричество?
Да не, он просто проигнорировал
1. Добавить запись о начале отправки;2. Отправить письмо;3. Изменить статус на Отправлено.
вот что с людьми такое, а?


Givv

Givv,Вы представляете, что происходит с обычной транзакцией, когда выключается электричество?
Видимо изменения откатятся, но тут вопрос в том что #3 может даже не начатся


Givv

что #3 может даже не начатся
где не прошла строчка коммит, откатится. В чем проблема? В письме отката? )))


Givv

где не прошла строчка коммит, откатится. В чем проблема? В письме отката? )))
Ну в том, что письмо будет отправлено, но в базе флаг Sent=0.


Givv

Givv,Ты пишешь программу с допуском по вероятности событий.Так что конкретнее вопрос.


Givv

Ну в том, что письмо будет отправлено, но в базе флаг Sent=0.
Вкл. Автокоммита в драйвере и коммит будет через миллисекунду.Ок?


Givv

Ну в том, что письмо будет отправлено, но в базе флаг Sent=0.
Ну значит после включения электричества отправится второй раз и проставится Sent=1. Это проблема?


Givv

Ну значит после включения электричества отправится второй раз и проставится Sent=1. Это проблема?
Ну да, проблема. Там на самом деле не отправка емайла, а другая "внешняя" операция, которую нельзя вызывать дважды.


Givv

Видимо изменения откатятся, но тут вопрос в том что #3 может даже не начатся
За счёт чего они откатятся?


Givv

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


Givv

Ну в том, что письмо будет отправлено, но в базе флаг Sent=0.
если такое случиться, не будет никакой трагедии отправить письмо повторно после включения электричества. кроме того, сервер, который получил письмо в очередь на отправку может сообщить, что письмо уже было отправлено. в механизмах типа fire and forget невозможно обеспечить 100% абсолютно атомарную транзакционность, так как после fire нет обратной связи. элекстричество может отключиться не у вас, а где-то на промежуточных серверах, и вы будете думать, что отправили, но адресат ничего не получит. увы.


Givv

]За счёт чего они откатятся?
Я подозреваю, что за счет журналирования транзакций.


Givv

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