Как стать автором
Обновить

Комментарии 35

> Мы добавили в MongoDB транзакции, а ребята со stackoverflow оказались не компетентны

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

На самом деле, очень часто пишут, что в MongoDB нет транзакций, хотя там есть compare-and-set, поверх которых можно реализовать вариацию на тему MVCC, чем не транзакции?
По такой логике транзакции есть везде. В монго нету транзакции «из коробки».
при записи должен достигаться кворум (см. w) чтобы переживать падение машин
А можно поподробнее, как обеспечивается достижение кворума? Как определяется количество серверов, которое нужно передать в параметре w?
Кстати, если mongo сказала, что запись была успешно завершена, это ничего не значит и вы можете не увидеть эту запись после рестарта. Если конечно не включите журналирование. Но в таком случае скорость её работы падает настолько, что SQL решения работают быстрее.
Я не эксперт по монге, просто увидел: 1. поддержку cas 2. множество коментариев, что она не поддервивает не транзакций.

На самом деле на сайте монги механизм репликации расписан не достаточно точно, поэтому я не могу дать 100% гарантии, что в очень редких случаях (мастер упал до того как начал репликацию) все будет хорошо.

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

Дожидание репликации по всех серверов не решает проблему, но снижает её вероятность.

Кстати, даже с включенном журналированием мы можем получить выйгрыш в скорости за счет шардирования.
Я вопрос по поводу кворума задал из-за того, что с одной стороны есть параметр w и можно было бы ждать, пока данные уйдут более чем на половину машин, а с другой стороны, размер живой части кластера не так просто узнать. А ставить w равным количеству машин в кластере тоже нельзя: при деградации кластера вы никогда не дождетесь завершения записи. Год или два назад на конференции разработчики монги пожали плечами и сказали, что пока что оно работает вот так, удобного способа дождаться репликации на нужное количество машин нет.

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

Но когда RPS сервиса работающего на монге падает с 1000 до 100 при включении журналирования, это не радует. И шардирование душу не особо греет.
Вы говорите о транзакции в контексте непрерываемой записи в БД или атомарности записи на диск?

Первое — может быть. Но вот за что любят SQL — так это то, что если тебе на commit вернули «угу», значит данные на диске. Точно. И в правильном порядке. И если питание отрубят, то никакого «с счёта А списали $100500, а на счёт Б ещё не записали».

Как с этим?
Но вот за что любят SQL — так это то, что если тебе на commit вернули «угу», значит данные на диске. Точно. И в правильном порядке.

К сожалению нет. Жесткий диск сообщает о том, что он записал данные, когда они в его буфере, а не когда они записались. БД не знает, когда реально произошла запись. Можно установить хитрую настройку через DMA, которая запретит кешировать запись, но говорят, что не всегда и это помогает.
Давайте не путать мягкое с тёплым. Настройка правильно работающего Storage — забота системных администраторов, и это элементарно делается.

Вопрос в том, можете ли вы гарантировать запись на диск в транзакционной манере в mongo? Если нет, ваш наезд на ответы с stackoverflow выглядит школьным умничанием, «а я умею, а они дураки, говорят, что нет».
Будте так любезны читать ники тех, кому отвечаете и не путать людей. Автора статьи зовут shai_xylyd, а я kibergus.
Выкрутился! >:)
Ну просто в олане ответов со stack overflow я согласен именно с ответами. Если вам понадобились транзакции в mongo, то нужно очень хорошо подумать и либо найти способ отказаться от них, либо использовать SQL. Ручная реализация транзакция дело сложное и не факт, что оно того стоит. Если он понадобились то это серьезный звоночек, что надо остановиться и еще раз взвесить все за и против.

А про правильную настройку железа, тут как раз на Yac докладчик из facebook крайне советовал проверять железо и предупреждал, что винты и аппаратные RAID'ы кешируют записи, а некоторые из них делат это даже если установлены соответсвующие запреты.
Если хоть раз задуматься, как же реализована транзакционность в нынешних СУБД, то это натолкнет на мысль, что нужно не версии данным присваивать, а делать полноценные redo-логи.
Она реализована по разному, есть и MVCC, а для redo логов, если я не ошибаюсь нужна тесная интеграция с самим хранилищем или демон который будет очень часто её пинговать.
Способов реализации redo-логов может быть масса, главное принцип их работы.
redo логи в монге есть. Называются oplog. Используются для репликации данных между серверами.
Банковская система на монго? Ну… ну
Ну это просто классический пример, я не сумасшедший)
Банки разные бывают )
Если вы знаете банки, в которых MongoDB применяют для проведения транзаций — напишите плиз. Во-первых чтобы знать куда не суваться на всякий случай, а во-вторых чтоб пообщатся с программистами (опыта работы с монго наверное у них ни одна бочка).
Айти системы банков — сложная система, состоящая из множества различных подсистем, иногда даже не связанных между собой. Поэтому процессинговый центр может быть построен не на Mongo, но какие-от из сопутствующих сервисов легко можно строить на данном типе субд
Насколько я понимаю, приведенное в статье решение есть не что иное, как вариация двухфазового коммита. Непонятно о каком ACID идет речь, если Durability (как писали чуть выше) не выполняется при отключенном журналировании. Да и с уровнями изоляций таких вот «транзакций» по моему есть проблемы.
На мой взгляд все эти сложности транзакций Mongo искусственные и притянутые за уши, из-за неправильного использования NoSQL, которое сейчас суют куда ни попадя. Я не отрицаю, что MongoDB это хорошее решение, если схема данных приложения идеально ложится на концепцию слабо связных документов, где в рамках отдельно взятого документа можно хранить достаточно большое количество информации. В этом случае можно отделаться атомарностью update-ов и в принципе не возникнет проблем с транзакциями. Но вот если у вас приложение, которое оперирует с финансами или с другими данными, которые имеют много зависимостей друг от друга и не могут быть представлены в виде единичных документов, то не используйте всякие уродливые хаки NoSQL! Используйте нормальные РСУБД и не парьтесь.
Но в реальности не всегда все так просто. Например, для ecommerce решений документная схема подходит лучше, чем тот же EAV на РСУБД. Но когда дело доходит до реализации финансовой части, начинает не хватать транзакций. Вот и приходится делать выбор, либо использовать два разных типа базы данных одновременно.
Это конечно сильно притянуто за уши, но почему не хранить сущности, требующие EAV (продукты, категории, добавить нужное) в монго, в базе держать какую-то неизменяемую часть продукта (SKU, GTIN код, название продукта например), а составную корзин и заказов хранить в РСУБД? Конечно, рой технологих это ничего хорошего, но кесарю кесарево, а нам наше. Как-то так.
Мысль, что под конкретные задачи нужно выбирать конкретные инструменты, которые справляются с этой задачей на 5 с плюсом, не дает мне покоя.
Есть и другие варианты — например, использовать XML-хранилище того же SQL Server. Там и индексы можно настраивать, и выборки делать по относительно сложным критериям.
Абсолютно здравая мысль. Существующие NoSQL решения — в том числе и MongoDB — не выполняют и половины ACID свойств, попытки реализовать их искусственно выглядят нелепо и противоречат самой природе таких программных средств. С другой стороны, уверенность в том, что в распределенных системах консистентность (вкупе с высокой скоростью и доступностью, естественно) невозможна в принципе, тает после того, когда читаешь публикации Гугла об их Спаннере и F1.
Насколько понимаю, в МонгоДБ используется понятие кворума? Что будет с этой самой «транзакцией», если количество реплик будет равно или превышать сумму кворумов на изменение/чтение? Это ведь классический пример eventual consistency.
Не верно, это вариация MVCC, а описанный там метод либо не работает в многопоточной среде, либо требуют чтобы:
  • все изменения над одним элементом были коммутативны и ассоциативны
  • каждый поток имел id, эти потоки никогда не умирали и общались между собой


По поводу ACID, вы правы, я отредактировал статью.
Статья интересная.
На днях тоже столкнулся с отсутствием транзакционности в MongoDB.
Но мысль неправильная проскальзывает — MongoDB как не была ACID, так и не есть ACID, и всё, что мы дописываем — это наши костыли, а сама Mongo из коробки — нетранзакционна.

Раз уж решение кажется таким простым, то все эти ребята из 10gen — малость идиоты, что уже не выпустили такую «фичу» в очередном релизе, без костылей?
Я думаю, что нет.

Цитата из мануала:

Does MongoDB support transactions?
MongoDB does not provide ACID transactions.
Спасибо, я немного подправил статью, основная идея, в том, как можно реализовать транзакции поверх compare-and-set, а монго, это только пример.
Сверху уже давали ссылку на описание two phase commit, заметьте — она находиться в официальной документации. Почему-то часто забывают, что MongoDB заточена под распределенность. А знаете как реализованы распределенные транзакции в, например, Oracle? Правильно — всё тот же two phase commit.
По поводу Durability — настоящая надежность обеспечивается только репликацией. Можно даже без журналирования. Односерверная конфигурация не переживет физического уничтожения сервера в любой базе данных.
Верно, я читал этот документ. Описанные там двух фазные транзакции либо не работают в многопоточной среде, либо требуют чтобы:
  • все изменения над одним элементом были коммутативны и ассоциативны
  • каждый поток имел id, эти потоки никогда не умирали и общались между собой
А пример сценария можно, при котором данный метод не работает в многопоточной среде?
Очень просто, заменяем коммутативное сложение в их примере, на некоммутативное приравнивание. Пусть наша модель состоит из двух переменных и модель считается консистентной, когда переменные равны друг другу. Смотрим, что может получиться, при двух параллельных транзакциях.

// начальное состояние
db.var.save({name: "a", value: 1, tx: []})
db.var.save({name: "b", value: 1, tx: []})

// создаем транзакции (будем считать, что мы их уже перевели в pending)
db.txs.save({changes : [{a : 2}, {b : 2}], state: "pending"})
// { "_id" : ObjectId("5072b0ee39d8ecf4ceb7865b"), "changes" : [ { "a" : 2 }, { "b" : 2 } ], "state" : "initial" }
db.txs.save({changes : [{a : 3}, {b : 3}], state: "pending"})
// { "_id" : ObjectId("5072b3ca39d8ecf4ceb7865c"), "changes" : [ { "a" : 3 }, { "b" : 3 } ], "state" : "initial" }

// константы
var tx1 = db.txs.findOne({_id:ObjectId("5072b0ee39d8ecf4ceb7865b")})
var tx2 = db.txs.findOne({_id:ObjectId("5072b3ca39d8ecf4ceb7865c")})

// step2 из туториала (две транзакции в перемешку)
db.vars.update({name: "a", tx: {$ne: tx1._id}}, {$set: {value: 2}, $push: {tx: tx1._id}})
// оба-на уже неконсистентное состояние a=2, b=1, но это можно простить так как транзакции еще выполняются
db.vars.update({name: "b", tx: {$ne: tx2._id}}, {$set: {value: 3}, $push: {tx: tx2._id}})
db.vars.update({name: "b", tx: {$ne: tx1._id}}, {$set: {value: 2}, $push: {tx: tx1._id}})
db.vars.update({name: "a", tx: {$ne: tx2._id}}, {$set: {value: 3}, $push: {tx: tx2._id}})

// остальные шаги я опустил, так как они не меняют value
// состояние базы после успешного завершения транзакций
db.vars.find()
// { "_id" : ObjectId("5072b07739d8ecf4ceb7865a"), "name" : "a", "tx" : [ ], "value" : 3 }
// { "_id" : ObjectId("5072b06f39d8ecf4ceb78659"), "name" : "b", "tx" : [ ], "value" : 2 }

Получилось, что после успешного(!) выполнения двух транзакций, база находиться в неконсистентном состоянии. Спрашивается, почему?
В данном случае можно было бы и записывать старое значение, а затем делать compare and swap.

Вот что пугает, так это step2. Вся эта магия кажется бесполезной, если нет нормальной изоляции.
Когда изучал монго и CouchDB… очень хотелось получить MVCC в монге… и нашел такую штуку, может кому будет интересно:
github.com/igd-geo/mongomvcc/wiki
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории