Требуется ли когда-либо транзакционное поведение вне баз данных? - PullRequest
13 голосов
/ 18 ноября 2008

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

  • файловые системы
  • веб-сервисов (ни один из которых я не использовал)

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

Я хотел бы знать, почему базы данных являются особым случаем?

Есть ли какие-нибудь полезные ссылки на тему транзакционного поведения вне баз данных?

Ответы [ 7 ]

16 голосов
/ 18 ноября 2008

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

Я реализовал механизм транзакций приложения (в .NET), который отличается от транзакции базы данных. На самом деле это довольно просто (несколько часов работы, включая тестовый набор). Он полностью написан на C # без каких-либо зависимостей от какой-либо функциональности базы данных или любого другого компонента. Но сначала немного контекста ...

Эта функция без транзакций базы данных существует в нескольких проявлениях на платформе Java, например, с EJB, ESB, JMS, и часто в связи с BPM. Некоторые из этих проявлений используют базовую базу данных, но не всегда и не по необходимости. Другие платформы имеют сопоставимые проявления, такие как MSMQ.

Большинство устаревших систем контроля версий НЕ реализуют семантику транзакций ACID. Как сказал ddaa, CVS не делает, а делает Subversion (его преемник). Visual Source Safe этого не делает. Если вы исследуете Subversion, вы можете найти сравнительные таблицы, которые подтверждают это.

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

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

Разрешите, пожалуйста, изложить сценарий. Вы и коллега разрабатываете приложение и используете Subversion для репозитория исходного кода. Вы оба пишете код и время от времени добавляете в хранилище. Вы вносите несколько изменений, запускаете чистую сборку (перекомпилируете все исходные файлы) и все тесты проходят. Итак, вы делаете свои изменения и идете домой. Ваш коллега работает над своими собственными изменениями, поэтому он также запускает чистую сборку, видит все тесты пройденными и фиксирует их в хранилище. Но ваш коллега затем обновляется из репозитория, делает еще несколько изменений, запускает чистую сборку, и сборка взрывается ему в лицо! Он отменяет свои изменения, обновления из хранилища снова (просто чтобы быть уверенным), и обнаруживает, что чистая сборка все еще взрывается! Ваш коллега проводит следующие пару часов, устраняя неполадки в сборке и источнике, и в конечном итоге находит изменения, которые вы внесли перед уходом, что приводит к сбою сборки. Он отправляет вам и вашему боссу неприятное электронное письмо с жалобой на то, что вы сломали сборку, а затем небрежно пошли домой. Вы прибываете утром, чтобы найти вашего коллегу и вашего начальника, ожидающих вас за столом, а все остальные наблюдают за вами! Таким образом, вы быстро запускаете чистую сборку и показываете, что сборка не сломана (все тесты проходят, как и прошлой ночью).

Итак, как это возможно? Это возможно, потому что каждая рабочая станция разработчика не является частью транзакции ACID; Subversion гарантирует только содержимое хранилища. Когда ваш коллега обновился из хранилища, его рабочая станция содержала смешанную копию содержимого хранилища (включая ваши изменения) и его собственные незафиксированные изменения. Когда ваш коллега выполнил чистую сборку на своей рабочей станции, он вызывал бизнес-транзакцию, которая НЕ была защищена семантикой ACID. Когда он отменил свои изменения и выполнил обновление, его рабочая станция соответствовала хранилищу, но сборка все еще была повреждена. Зачем? Потому что ваша рабочая станция была также частью отдельной бизнес-транзакции, которая также НЕ была защищена семантикой ACID, в отличие от вашей фиксации в хранилище. Поскольку вы не обновляли свою рабочую станцию ​​до соответствия хранилищу перед запуском чистой сборки, вы на самом деле не собирали исходные файлы, как они существовали в хранилище. Если вы произвели такое обновление, вы обнаружите, что сборка также не удалась на вашей рабочей станции.

Теперь я могу изложить свою исходную точку - транзакции имеют контекст / контекст, который необходимо тщательно продумать. Тот факт, что у вас есть транзакция ACID, не означает, что ваша бизнес-логика безопасна, НЕ РАЗРЕШАЕТСЯ объем / контекст транзакции ACID, и бизнес-логика точно соответствует. Если вы полагаетесь на какую-либо форму транзакции ACID базы данных, но вы делаете НИЧЕГО в своей бизнес-логике, которая не покрывается этой транзакцией базы данных, то у вас есть пробел, который может допустить сопоставимую и катастрофическую ошибку. Если вы можете заставить свою бизнес-логику точно соответствовать транзакции базы данных, то все в порядке. Если нет, то вам, вероятно, нужна отдельная бизнес-операция. В зависимости от характера незащищенной логики вам может потребоваться реализовать собственный механизм транзакций.

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

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

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

9 голосов
/ 18 ноября 2008

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

Поддержка транзакций - это функция, которая предоставляет ACID свойства. С точки зрения непрофессионала, это означает, что транзакция - это то, что позволяет: 1. объединить несколько дискретных операций в один пакет, который либо завершается успешно, либо завершается неудачей в целом; 2. скрывает незафиксированные изменения для одновременных пользователей, так что 3. одновременных пользователей всегда иметь «согласованное» представление о системе.

Файловые системы традиционно предлагают некоторый механизм блокировки, но это отличается от предоставления транзакций. Однако все файловые системы имеют некоторые атомарные свойства. Например, если у вас есть каталоги /a/ и /b/, и вы одновременно пытаетесь выполнить mv /a /b/a и mv /b /a/b, только одна из этих операций будет выполнена успешно, без ущерба для целостности. Чего обычно не хватает файловым системам, так это способности объединять несколько операций в один изолированный атомарный пакет.

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

Другой ответ упомянул системы обмена сообщениями как транзакционные. Я не читал связанный материал, но в самом ответе упоминалась только атомная доставка сообщений. Это не транзакции.

Я никогда не слышал о Clojure до того, как Брайан С. упомянул это здесь. Мне кажется, что это действительно реализация транзакций вне контекста базы данных. Здесь основное внимание уделяется контролю параллелизма, а не обеспечению согласованности надежных данных.

Таким образом, за исключением Clojure, похоже, что любая система, которая нуждается в транзакциях, либо использует базовую базу данных, либо превращает себя в базу данных.

7 голосов
/ 18 ноября 2008

Современные файловые системы имеют транзакции. Они просто прозрачны для конечного пользователя.

NTFS, XFS, JFS, EXT3 и ReiserFS все делают, просто чтобы назвать несколько.

И это только внутренняя часть файловой системы. Многие ОС также поддерживают блокировку файлов (см., Например, flock (2) в мире * NIX) с эксклюзивной блокировкой (запись) и общей (чтение) блокировкой.

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

5 голосов
/ 18 ноября 2008

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

4 голосов
/ 18 ноября 2008

Системы обмена сообщениями являются еще одним примером менеджеров транзакционных ресурсов.

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

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

Больше информации на

3 голосов
/ 18 ноября 2008

Коммиты Subversion являются транзакционными: они действительно атомарны, поэтому прерванный коммит не оставляет репозиторий в несовместимом состоянии.

1 голос
/ 02 декабря 2010

У меня была ситуация, в которой мне нужно было рассматривать файловую систему и базу данных как одну транзакционную единицу.

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

http://www.databasesandlife.com/atomic-operations-over-filesystem-and-database/

...