Re: [IndexedDB] Interaction between transactions and objects that allow multiple operations

On May 4, 2010, at 7:17 PM, Pablo Castro wrote:

> The interaction between transactions and objects that allow multiple operations is giving us trouble. I need to elaborate a little to explain the problem.
> 
> You can perform operations in IndexedDB with or without an explicitly started transaction. When no transaction is present, you get an implicit one that is there for the duration of the operation and is committed and the end (or rolled-back if an error occurs).

To provide context to those who might be missing it, an explicit transaction is active in an IndexedDB Database as long as it has not been explicitly committed or aborted. An implicit transaction's life time is under the control of the implementation and spans no more than the operation requested.

> 
> There are a number of operations in IndexedDB that are a single step. For example, store.put() occurs either entirely in the current transaction (if the user started one explicitly) or in an implicit transaction if there isn't one active at the time the operation starts. The interaction between the operation and transactions is straightforward in this case.
> 
> On the other hand, other operations in IndexedDB return an object that then allows multiple operations on it. For example, when you open a cursor over a store, you can then move to the next row, update a row, delete a row, etc. The question is, what is the interaction between these operations and transactions? Are all interactions with a given cursor supposed to happen within the transaction that was active (implicit or explicit) when the cursor was opened? Or should each interaction happen in its own transaction (unless there is a long-lived active transaction, of course)?

The transactional context of a series of operations is the transaction that was created in the database. Each and every operation from that point on till one of the following happens is performed in that transaction:

1. The transaction is committed
2. The transaction is aborted
3. The database object goes out of scope.

> 
> We have a few options:
> a) make multi-step objects bound to the transaction that was present when the object is first created (or an implicit one if none was present). This requires new APIs to mark cursors and such as "done" so implicit transactions can commit/abort, and has issues around use of the database object while a cursor with an implicit transaction is open.
> 
> b) make each interaction happen in its own transaction (explicit or implicit). This is quite unusual and means you'll get inconsistent reads from row to row while scanning unless you wrap cursor/index scans on transactions. It also probably poses interesting implementation challenges depending on what you're using as your storage engine.
> 
> c) require an explicit transaction always, along the lines Nikunj's original proposal had it. We would move most methods from database to transaction (except a few properties such as version and such, which it may still be ok to handle implicitly from the transactions perspective). This eliminates this whole problem altogether at the cost of an extra step required always.
> 
> We would prefer to go with option c) and always require explicit transactions. Thoughts?

The current specification allows using an explicit transaction and once initiated, the explicitly created transaction is applicable for its life time as described above. IOW a) is the same as c)

If you intend to perform multiple steps, then an explicit transaction appears to be in order unless the application can tolerate inconsistent results. Therefore b) is not a good idea for multi-step operations. In addition, it is not a good idea to create/commit explicit transactions for each operation.

There has been some discussion for nested transactions and the original proposal had support for those, but recall that some implementors were not convinced of the cost/benefit tradeoff on that one.

Nikunj

Received on Thursday, 6 May 2010 08:15:38 UTC