Как TransactionScope гарантирует целостность данных в нескольких базах данных?

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

Изменить:

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

Спасибо, Бас

Пример:

    using(var scope=new TransactionScope())
    {
        using (var context = new FirstEntities())
        {
            context.AddToSomethingSet(new Something());
            context.SaveChanges();
        }

        using (var context = new SecondEntities())
        {
            context.AddToSomethingElseSet(new SomethingElse());
            context.SaveChanges();
        }

        scope.Complete();
    }

person Bas Smit    schedule 08.03.2010    source источник
comment
кстати, вы выполняете сериализованную транзакцию изоляции в своем коде.   -  person Henrik    schedule 20.01.2012


Ответы (2)


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

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

Это не так. Я думаю, что это известно как проблема генералов. Доказуемо, что это невозможно предотвратить. Окна отказа, однако, довольно малы.

person usr    schedule 08.03.2010
comment
Насколько я понимаю статью в Википедии о проблеме генералов, учитывая, что сообщение и его подтверждение успешно обменялись (он же произвольный шаг, прописанный в tx-логе), 2PC избегает несоответствий. Если ваша сеть выходит из строя после того, как одна из них зафиксировалась, а другая еще нет, первая будет успешно подготовлена, как и другая (иначе им не будет сказано зафиксировать), и в этот момент первая база данных может безопасно принять вторую база данных зафиксирует, когда она вернется в сеть. - person Henrik; 26.03.2010
comment
Это верно только в том случае, если вы предполагаете, что может быть потеряно только ограниченное количество сообщений. Если все сообщения могут быть потеряны в самый неподходящий момент, вы все равно проиграете. - person usr; 09.02.2011

Он продвигает его до координатора распределенных транзакций (msdtc), если обнаруживает несколько баз данных, которые используют каждую область как часть двухэтапной фиксации. Каждая область действия голосует за фиксацию, поэтому мы получаем свойства ACID, но распределенные по базам данных. Он также может быть интегрирован с TxF, TxR. Вы должны быть в состоянии использовать его так, как вы описываете.

Две базы данных согласованы, так как распределенная транзакция COM+, работающая под MTC, присоединила к ним транзакции базы данных.

Если одна база данных голосует за фиксацию (например, выполнив (:TransactionScope).Commit()), «она» сообщает DTC, что она голосует за фиксацию. Когда все базы данных сделали это, у них есть список изменений. Поскольку транзакции базы данных теперь не блокируются и не конфликтуют с другими транзакциями (например, с помощью алгоритма справедливости, который вытесняет одну транзакцию), все операции для каждой базы данных находятся в журнале транзакций. Если система теряет питание, когда фиксация еще не завершена для одной базы данных, но уже завершена для другой, в журнале транзакций будет записано, что все ресурсы проголосовали за фиксацию, поэтому логически не подразумевается, что фиксация должна завершиться неудачно. Следовательно, в следующий раз, когда база данных, которая не смогла зафиксироваться, загрузится, она завершит те транзакции, которые остались в этом неопределенном состоянии.

person Henrik    schedule 08.03.2010
comment
Спасибо за ответ, но я все еще немного озадачен. В какой-то момент нужно указать обеим базам данных применить свои изменения. Допустим, произошло отключение питания после того, как первая БД была применена, тогда базы данных не синхронизированы. Или я что-то упускаю? - person Bas Smit; 08.03.2010
comment
Я имею в виду, что обе базы данных по отдельности действительны, но они больше не синхронизируются друг с другом. - person Bas Smit; 08.03.2010
comment
Я добавил больше к своему ответу. См. ссылку на Википедию для получения дополнительных ссылок и ресурсов. Короче; он работает без рассинхронизации баз данных (они также используют 2PC внутри), если вы используете TransactionScopes, так что вам не о чем беспокоиться. Однако к этому ответу можно применить дополнительные детали, например, запись на диск на самом деле не является атомарной, вопреки предположениям систем баз данных, и какие типы жестких дисков вы должны использовать, чтобы гарантировать как можно больше (forums.bit-tech.net/showthread.php?t=146156) - person Henrik; 08.03.2010
comment
@Bas Smit: С уважением, Хенрик уже дал вам ссылки, в которых подробно описывается, как работает 2PC. В частности, см. ссылку на Бернштейна внизу статьи в Википедии. Вопросы, которые вы задаете, не новы, и вы можете либо (1) прочитать о 2PC, если хотите узнать, как работает восстановление, либо (2) просто признать, что эти проблемы поднимались ранее. Хенрик ответил на ваш вопрос, и ему не нужно излагать все детали довольно сложного протокола. - person Craig Stuntz; 08.03.2010