- From: Jonas Sicking <jonas@sicking.cc>
- Date: Wed, 26 Nov 2008 11:31:31 -0800
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
Received on Wednesday, 26 November 2008 11:31:31 UTC