Многочисленные, многодокументные «транзакции» в MongoDB
Я понимаю, что MongoDB, под этимСама природа, не правда ли?и, вероятно, никогда не будет поддерживать такие транзакции. Тем не менее, я обнаружил, что мне нужно использовать их несколько ограниченным образом, поэтому ямы придумали следующее решение, и ямне интересно:это лучший способ сделать это, и можно ли его улучшить? (прежде чем я пойду и осуществлю это в моем приложении!)
Очевидно, что транзакция контролируется через приложение (в моем случае, веб-приложение Python). Для каждого документа в этой транзакции (в любой коллекции) добавляются следующие поля:
'lock_status': bool (true = locked, false = unlocked),
'data_old': dict (of any old values - current values really - that are being changed),
'data_new': dict (of values replacing the old (current) values - should be an identical list to data_old),
'change_complete': bool (true = the update to this specific document has occurred and was successful),
'transaction_id': ObjectId of the parent transaction
Кроме того, естьtransaction
коллекция, в которой хранятся документы, подробно описывающие каждую транзакцию. Они похожи:
{
'_id': ObjectId,
'date_added': datetime,
'status': bool (true = all changes successful, false = in progress),
'collections': array of collection names involved in the transaction
}
И здесь'С логикой процесса. Надеюсь, это работает так, что если этоЕсли оно прервано или не выполнено каким-либо другим способом, его можно откатить должным образом.
1: Настроитьtransaction
документ
2: Для каждого документа, на который влияет эта транзакция:
Задаватьlock_status
вtrue
(к 'замок' документ от изменения)Задаватьdata_old
а такжеdata_new
к их старым и новым ценностямЗадаватьchange_complete
вfalse
Задаватьtransaction_id
в ObjectId изtransaction
документ, который мы только что сделали3: Выполните обновление. Для каждого затронутого документа:
Замените все затронутые поля в этом документе наdata_new
ценностиЗадаватьchange_complete
вtrue
4: Установитьtransaction
документаstatus
вtrue
(так как все данные были успешно изменены)
5: Для каждого документа, затронутого транзакцией, выполните некоторую очистку:
удалитьdata_old
а такжеdata_new
, как они'больше не нужнызадаватьlock_status
вfalse
(чтобы разблокировать документ)6: Удалитьtransaction
документ, созданный на шаге 1 (или, как предлагается, пометьте его как завершенный)
Я думаю, что это логически работает таким образом, что если в любой момент происходит сбой, все данные можно откатить или продолжить транзакцию (в зависимости от того, что вы хотите сделать). Очевидно, что все откат / восстановление / и т. Д. выполняется приложением, а не базой данных, используяtransaction
документы и документы в других коллекциях с этимaction_id.
Есть ли явная ошибка в этой логике, что япропустили или упустили из виду? Есть ли более эффективный способ сделать это (например, меньше писать / читать из базы данных)?