Несколько транзакция базы данных

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

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

  1. Откатывайте транзакцию для первого обновления, или
  2. кэшируйте вызов к веб-сервисам и продолжайте звонить в веб-сервисы, пока сервисы не станут доступными
  3. Некоторые другие методы, которые могут поддержать несколько целостность БД.

А именно, я ищу синтаксис как

void RootMethod()
{
     using(TransactionScope scope = new TransactionScope())
     {
        try
         { 
          SomeMethod();
          scope.Complete();
          CallWebService();
         }
         catch
         {
             scope.abort();
          }
     }
}

Но не уверенный, ли

  1. Это - хорошая техника
  2. Или это выполнимое в симфонии как в C#

Что Вы думаете?

Править: Некоторые спросили меня, почему существует потребность в двух обновлениях части. Это - потому что я создаю клиентское приложение, соединяющееся с существующим приложением бэкэнда. И я не хочу изменять приложение бэкэнда. Так неизбежно будет некоторое перекрытие. Поэтому существует потребность синхронизировать данные

Другое Редактирование: Эти две транзакции частей должны быть сделаны вместе, делание задания крона для синхронизации таблицы не желательно

6
задан Graviton 28 February 2009 в 03:23
поделиться

8 ответов

Это будет хитрым. Вам нужны 2 фиксации фазы для надежного решения, но это было бы тонной работы для реализации для определенных потребностей.

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

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

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

Удачи.

4
ответ дан 8 December 2019 в 12:23
поделиться

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

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

Это - основной алгоритм:

begin transaction;
do local work;
save information for external call;
set an appropriate time for next attempt;
mark external call as not performed;
commit work;

begin transaction;
make external call;
if successful
   mark external call as performed (or delete the record)
else
   set the time for the next attempt
commit;

Вам затем нужны регулярная задача, поток, или независимо от того, что это делает что-то вроде этого:

for each record where the time for the next attempt <= now
    begin work;
    if the remote service has not performed this transaction
        make the remote call;
        if successful
            mark as done;
        else if too many attempts
            mark the transaction as permanently failed;
            alert operator;
        else
            set the time for the next attempt;
        endif
    else
        mark as done;
    endif

    commit;
 endfor

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

Основные отказы:

  1. Отказ перед первой фиксацией завершается: Все откатывает.

  2. Отказ после первой фиксации, но перед веб-сервисом завершается (это включает отказы из-за переходного процесса в сам веб-сервис): удаленная транзакция веб-сервиса воспроизводится задачей восстановления.

  3. Отказ после веб-сервиса завершается, но прежде чем вторая фиксация завершается: дублирующаяся транзакция веб-сервиса обнаруживается задачей восстановления, и локальная запись исключается из очереди.

  4. Отказы в задаче восстановления: По существу то же как отказы во второй транзакции.

Другие примечания:

  • Постепенный подход возврата полезен для отказов. Если существует отказ из-за переходного процесса на сервисе, Вы хотите замедлить свои повторения.

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

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

Ответ на дополнительное требование: "Эти две транзакции частей должны быть сделаны вместе, делание задания крона для синхронизации таблицы не желательно"

Мое чтение этого требования: "эти две системы никогда не должны перестать работать".

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

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

Если Вы действительно получаете решение этой проблемы, которая отвечает требованиям наличия двух отдельных систем, последовательных через несколько транзакций, и никогда не требует последующего согласования после отказа, необходимо описать его и публиковать его в Журнале VLDB, ACM TODS или IEEE TKDE.

5
ответ дан 8 December 2019 в 12:23
поделиться

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

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

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

Действительно Ваш ответ зависит от тех вопросов. Не делайте ошибку предположения, что Ваша вся программа откажет, если вещами составят 0,01% из синхронизации в течение 10 минут. Фигура, каковы приемлемые поля для ошибок.

3
ответ дан 8 December 2019 в 12:23
поделиться

Не пытайтесь создать 2-фазную логику управления транзакциями сами. Вы будете понимать его превратно, доверять мне. Если это доступно в Вашей proggy среде, как это находится в C#, то используйте его. В противном случае затем не идите, создавая его сами.

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

таким образом ограничьте свою транзакцию локальными ресурсами:

make a change to reliable store (I believe this would be called a "resource" in X/Open transaction parlance)
enqueue a record of that change in a disk-backed log

затем, в расписании (каждый час, каждый день, безотносительно)

while not done
    pop item from queue or log
    sync that change with the external, remote resource

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

2
ответ дан 8 December 2019 в 12:23
поделиться

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

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

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

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

Моим личным выбором был бы номер 1. Откатывайте локальную транзакцию, если это не абсолютно не возможное применение номер 2.

2
ответ дан 8 December 2019 в 12:23
поделиться

Возможно, Вы могли попытаться не поместить эту логику нескольких обновлений в Вашем приложении, но использовать внешний процесс, который знает, что обновить, когда и что сделать, если обновление перестало работать. Oracle BPEL, например, является таким процессом. Можно настроить его для организации различных сервисов, поскольку пример видит http://alisonatoracle.blogspot.com/2006_01_01_archive.html

Могло бы быть излишество для Вашего приложения, хотя, в зависимости от он - размер...

1
ответ дан 8 December 2019 в 12:23
поделиться

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

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

1
ответ дан 8 December 2019 в 12:23
поделиться

Я не понял, Ваше приложение в PHP или в C#? Если это находится в C# (WCF), и веб-сервис является WCF (или поддерживает WS-AtomicTransaction), то это возможно.

1
ответ дан 8 December 2019 в 12:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: