2009-02-18 5 views
5

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

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

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

В частности, я ищу синтаксис как

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

Но не уверен, является ли

  1. Это хороший метод
  2. Или это возможно в Symfony, как в C#

Как вы думаете?

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

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

ответ

4

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

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

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

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

Удачи.

+2

Сохранение транзакции открыто во время вызова веб-службы по-прежнему оставляет окна, в которых состояние является непоследовательным. Появляется окно, в котором локальная транзакция возвращается, но транзакция веб-сервиса завершается. – janm

1

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

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

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

Для этого потребуется отслеживание состояния данных и его успешное выполнение с обоих концов.

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

+0

* Зачем вам нужно синхронизировать две базы данных в самом приложении, можете ли вы синхронизировать его каждый час? * Это потому, что я создаю приложение переднего конца для существующего приложения на заднем плане. Поэтому неизбежно произойдет некоторое перекрытие. Поэтому необходимо синхронизировать данные. – Graviton

1

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

link text

+0

Это PhP, а не C# – Graviton

4

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

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

Это базовый алгоритм:

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 

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

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

Сбой перед первым совершающих: Завершает все откат.

Сбой после первого коммита, но до завершения веб-службы (включая кратковременные сбои в самой веб-службе): Удаленная транзакция webservice воспроизводится задачей восстановления.

Сбой после завершения веб-службы, но до завершения второй фиксации: транзакция дублированного веб-сервиса обнаруживается задачей восстановления, а локальная запись удаляется.

Неудачи в задаче восстановления: по существу такие же, как и ошибки во второй транзакции.

Другие ноты:

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

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

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

Ответ на дополнительное требование: «Сделка две части должно быть сделано вместе, выполняя задания хрон синхронизировать таблицу не желательно»

Мое чтение этого требования: «две системы никогда не потерпит неудачу ».

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

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

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

2

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

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

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

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

+0

Это хороший ответ .. но предположил, что я только готов терпеть из-за ситуации синхронизации в течение 10 минут? – Graviton

+0

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

+0

«только терпеть ситуацию не в синхронизации в течение 10 минут»: вернуть вселенную обратно в место покупки для полного возмещения. Что происходит, если веб-служба умирает раньше, подтверждает завершение и остается в течение часа? Вы не знаете, было ли оно совершено или откат назад, пока оно не вернется. – janm

2

Не пытайтесь построить 2-фазная логика управления транзакциями самостоятельно. Вы ошибетесь, поверьте мне. Если он доступен в вашей проггистой среде, как в 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 

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

1

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

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

1

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

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

Смежные вопросы