title: Multi-collection, multi-document 'transactions' in MongoDB
body: <p>I realise that MongoDB, by it's very nature, doesn't and probably never will support these kinds of transactions.  However, I have found that I do need to use them in a somewhat limited fashion, so I've come up with the following solution, and I'm wondering: <strong>is this the best way of doing it, and can it be improved upon?</strong> (before I go and implement it in my app!)</p>
  
  <p>Obviously the transaction is controlled via the application (in my case, a Python web app).  For each document in this transaction (in any collection), the following fields are added:</p>
  
  <pre><code>'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
  </code></pre>
  
  <p>In addition, there is a <code>transaction</code> collection which stores documents detailing each transaction in progress.  They look like:</p>
  
  <pre><code>{
      '_id': ObjectId,
      'date_added': datetime,
      'status': bool (true = all changes successful, false = in progress),
      'collections': array of collection names involved in the transaction
  }
  </code></pre>
  
  <p>And here's the logic of the process. Hopefully it works in such a way that if it's interupted, or fails in some other way, it can be rolled back properly.</p>
  
  <p><strong>1:</strong> Set up a <code>transaction</code> document</p>
  
  <p><strong>2:</strong> For each document that is affected by this transaction:</p>
  
  <ul>
  <li>Set <code>lock_status</code> to <code>true</code> (to 'lock' the document from being modified)</li>
  <li>Set <code>data_old</code> and <code>data_new</code> to their old and new values</li>
  <li>Set <code>change_complete</code> to <code>false</code></li>
  <li>Set <code>transaction_id</code> to the ObjectId of the <code>transaction</code> document we just made</li>
  </ul>
  
  <p><strong>3:</strong> Perform the update. For each document affected:</p>
  
  <ul>
  <li>Replace any affected fields in that document with the <code>data_new</code> values</li>
  <li>Set <code>change_complete</code> to <code>true</code></li>
  </ul>
  
  <p><strong>4:</strong> Set the <code>transaction</code> document's <code>status</code> to <code>true</code> (as all data has been modified successfully)</p>
  
  <p><strong>5:</strong> For each document affected by the transaction, do some clean up:</p>
  
  <ul>
  <li>remove the <code>data_old</code> and <code>data_new</code>, as they're no longer needed</li>
  <li>set <code>lock_status</code> to <code>false</code> (to unlock the document)</li>
  </ul>
  
  <p><strong>6:</strong> Remove the <code>transaction</code> document set up in step 1 (or as suggested, mark it as complete)</p>
  
  <hr>
  
  <p>I think that logically works in such a way that if it fails at any point, all data can be either rolled back or the transaction can be continued (depending on what you want to do).  Obviously all rollback/recovery/etc. is performed by the application and not the database, by using the <code>transaction</code> documents and the documents in the other collections with that transaction_id.</p>
  
  <p><strong>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)?</strong></p>