Многочисленные, многодокументные «транзакции» в MongoDB
Я понимаю, что MongoDB по самой своей природе не поддерживает и, вероятно, никогда не будет поддерживать такие транзакции. Однако я обнаружил, что мне нужно использовать их в некоторой степени, поэтому я пришел к следующему решению, и мне интересно:is this the best way of doing it, and can it be improved upon? (прежде чем я пойду и осуществлю это в моем приложении!)
Очевидно, что транзакция контролируется через приложение (в моем случае, веб-приложение 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: Для каждого документа, на который влияет эта транзакция:
Setlock_status
to true
(to 'lock' the document from being modified)
Set data_old
and data_new
to their old and new values
Set change_complete
to false
Set transaction_id
to the ObjectId of the transaction
document we just made
3: Выполните обновление. Для каждого затронутого документа:
Replace any affected fields in that document with thedata_new
values
Set change_complete
to true
4: Установитьtransaction
Документ & APOS; sstatus
вtrue
(так как все данные были успешно изменены)
5: Для каждого документа, затронутого транзакцией, выполните некоторую очистку:
remove thedata_old
and data_new
, as they're no longer needed
set lock_status
to false
(to unlock the document)
6: Удалитьtransaction
документ, созданный на шаге 1 (или, как предлагается, пометьте его как завершенный)
Я думаю, что это логически работает таким образом, что если в любой момент происходит сбой, все данные можно откатить или продолжить транзакцию (в зависимости от того, что вы хотите сделать). Очевидно, что все откат / восстановление / и т. Д. выполняется приложением, а не базой данных, используяtransaction
документы и документы в других коллекциях с этимaction_id.
Is there any glaring error in this logic that I've missed or overlooked? Is there a more efficient way of going about it (e.g. less writing/reading from the database)?