[whatwg] Database feedback

Jonas Sicking jonas at sicking.cc
Wed Nov 26 11:31:31 PST 2008


Ian Hickson wrote:
> There's a question at the bottom about how best to make transactions be 
> free of concurrency problems. Input welcome.
> 
> On Fri, 23 May 2008, Aaron Boodman wrote:
>> I noticed one unfortunate thing about the new Database API. Because the 
>> executeSql() callback holds open the transaction, it is easy to 
>> accidentally do intensive work inside there and hold open the 
>> transaction too long. A common mistake might be to do a big select and 
>> then hold open the transaction while the UI is updated. This could hold 
>> open the tx maybe an extra couple hundred ms. A bigger problem would be 
>> to do synchronous XHR (for example, in workers). This could hold open 
>> the tx for seconds.
>>
>> The right place to do work like this is in transaction()'s success 
>> callback. But because the resultsets aren't easily accessible there, I 
>> think authors are more likely to do work in executeSql()'s success 
>> callback and use transaction()'s success callback less frequently.
>>
>> Off hand about the best solution I can think of to this problem is to 
>> have some sort of state on the transaction object that gathers the 
>> results.
>>
>> This is not very satisfying though. Does anyone have a better idea? Or 
>> think this is not a big enough concern to worry about?
> 
> I agree that this might be a problem. I'm not sure how to address it.
> 
> 
> On Tue, 27 May 2008, Scott Hess wrote:
>> I think the only way you can really make it better is to put something 
>> like an executeSql() function directly on Database objects, which could 
>> shift the success callback entirely outside the transaction scope.  I 
>> think that would reasonably match server-side SQL use (you either send a 
>> bare SELECT with implicit transaction, or use explicit BEGIN/END to 
>> group things which must be consistent).
> 
> I don't want to add this yet, in case it turns out we don't really need 
> it, but implementation experience will definitely tell us whether this is 
> needed or not and if it is we will have to add it in v2.
> 
> 
> On Mon, 26 May 2008, Aaron Boodman wrote:
>> Quick thing. I don't think the spec makes it clear whether it is allowed 
>> to do this:
>>
>> var db1 = window.openDatabase("foo", "", "", "");
>> var db2 = window.openDatabase("foo", "1", "", "");
>>
>> I think the answer should be "no". Thoughts?
>>
>> If so, perhaps edit this sentence:
>>
>> If the database version provided is not the empty string, and the 
>> database already exists but has a different version, then the method 
>> must raise an INVALID_STATE_ERR exception.
>>
>> To read like this:
>>
>> If the database version provided is not the empty string, and the 
>> database already exists but has a different version, or no version, then 
>> the method must raise an INVALID_STATE_ERR exception.
> 
> Fixed.
> 
> 
> On Mon, 26 May 2008, Chris Prince wrote:
>> I think the spec is technically correct.  What's confusing is that the 
>> same line can mean two different things:
>>
>> // Start with no databases.
>>
>> // On the 1st call, this line means "create a database,
>> // and set the version string to the empty string".
>> var db1 = window.openDatabase("foo", "", "", "");
>>
>> // On the 2nd call, the meaning has changed to
>> // "open the 'foo' database, regardless of the version string".
>> var db2 = window.openDatabase("foo", "", "", "");
> 
> Yeah, that's a bit confusing. Not sure what to do about it.
> 
> 
> On Mon, 4 Aug 2008, Aaron Boodman wrote:
>> It seems like you need a way to abort an in-progress transaction. An 
>> easy way to do this would be to add an abort() method to SQLTransaction.
> 
> What's the use case? Can we wait until v2 to add this, or is it critical?
> 
> 
> On Mon, 4 Aug 2008, Aaron Boodman wrote:
>> Currently, the database API has an error code for the situation where 
>> you open a transaction for read, then try to write but the database is 
>> locked.
>>
>> I think that the spec should at least suggest, but perhaps require, 
>> implementors to serialize access to a single database to prevent this 
>> from happening. Without this, developers must wrap every single write 
>> attempt in error handling and retry if a lock error occurs.
>>
>> It seems likely that developers will forget to do this and it will be a 
>> significant pain point with the API. Applications will seem to work, but 
>> then mysteriously fail in production when users have multiple copies of 
>> the application open.
>>
>> Even if the developer adds retry logic, it is easy for a page to get 
>> starved by another page.
>>
>> Serializing access would prevent all these problems at the cost of read 
>> concurrency, which I think is OK for the first version of this API. A 
>> future version of the API could add the concept of "read transactions" 
>> which would allow concurrency, but would fail immediately when you try 
>> to write with them.
> 
> I am loath to do this, because of the performance hit. However, what we 
> could do is say that if the first statement is read-only, they all have to 
> be, and if the first statement is a write, then it locks the database? 
> Though that would be rather weird...
> 
> We could have a .writeTransaction() and a .readTransaction(), where the 
> former always run in isolation.
> 
> Any preferences?

I'm fine with either the perf-hit solution or the 
.writeTransaction/.readTransaction solution. Both seems better than 
having writes throw under basically race conditions. If we go with the 
perf-hit solution we can always add the speedier 
.writeTransaction/.readTransaction APIs in a later version.

/ Jonas



More information about the whatwg mailing list