Why does indexedDB use a "version"?
Asked Answered
P

3

22

I'm just learning about indexedDB, and this is my understanding of setting up a database. You call .open(dbName) to get a DB instance. If no database of this name exists on the user's computer (for instance if this is their first visit to the site) then this triggers an onUpdateNeeded event, which is therefore where you should do initialization stuff like creating the ObjectStores.

Now, you can also pass in a version - .open(dbName, version) - and if the database exists but uses a lower version, this forces an onUpdateNeeded event regardless. Now, I can see the utility of this... but why have an integer argument? If the point of the "version" argument is to force updates, why not just have a forceUpdate flag? Why have an integer version argument which you therefore need to increment ever higher as you debug your code, presumably reaching version 156 after many days of debugging?

Is the version used in some functionality that I'm not aware of beyond just forcing updates, and if not, what is the rationale behind it? Also, are you intended to just keep changing the version during development but keep it fixed once the app is released, or is the idea that you should keep changing it throughout the lifecycle of your app?

Psychobiology answered 15/12, 2015 at 21:56 Comment(2)
It is useful after you: shipped your program, someone used it, saved some data, and you made an update that stores data incompatibly. Of course, for local testing you'll just want to clear it every time.Kalk
New answers have been added to your question. Please review new answers to see if the currently selected Best Answer is still the best answer, and please consider upvoting any answer that provides information you find useful. Doing so will acknowledge the better-quality answers, which is helpful to the StackOverflow community.Superjacent
O
28

The monotonically increasing integer allows this pattern:

var open = indexedDB.open('db', 3);
open.onupgradeneeded = function(e) {
  var db = open.result;
  if (e.oldVersion < 1) {
    // create v1 schema
  }
  if (e.oldVersion < 2) {
    // upgrade v1 to v2 schema
  }
  if (e.oldVersion < 3) {
    // upgrade v2 to v3 schema
  }
  // ...
};
open.onsuccess = function() {
  var db = open.result;
  // ...
};

This is a very common pattern. Obviously, one could imagine that this is done manually - developers could track a version in a special metadata table - rather than enshrining it in the standard. But it's common enough that it was built-in, similar to indexes and key generators.

There's a valid argument that this makes the API too complicated for beginners, but without a time machine it's somewhat moot.

...

If you're debugging locally and the changes are constrained to your machine then deleting/recreating the database is probably easier than writing schema upgrade logic for each minor change.

Optime answered 17/12, 2015 at 0:59 Comment(9)
I have a personal followup question here: does each condition block for a new version actually need to migrate from every possible prior schema state? Where you state the comment upgrade v2 to v3, do you not have to always also consider the upgrade from v1 to v3 within the same block? E.g. a chrome extension upgrade containing a db schema that went through several local revisions between updates?Trout
Ooops, I made a mistake in my example. It should be checking the event's oldVersion, not the database's version. Fix coming...Optime
Okay, fix made - sorry about that. Since the if statements don't have elses, multiple blocks will run if necessary.Optime
And specifically... as written, the upgrade from v1 to v3 will be handled by upgrading v1 to v2, then v2 to v3.Optime
@JoshuaBell Can every form load use it's own version of IndexedDb? for instance, ID1- uses ver1, ID2- uses ver 2 of the db. We have a scenario where each form can use a different version of the lookup tables. The data needs to be versioned and each form ID needs to somehow fetch back that specific version of data it used.Vendace
Each database has a version. It sounds like you may want a separate database per "form".Optime
@JoshuaBell I just can't figure it out. What happens if an app grows rapidly and contains 100 versions?Wehner
@Wehner Presumably then your users's machines have 100 different possible database configurations on them, and you need your app to be able to handle this. The version number just codifies an extremely common pattern - how you use it is really up to you. One approach would be that if your app sees any older version on a user's system then you simply delete all the stores and start from scratch. If the data is just a cache that might be fine; if it contains critical user data (e.g. offline edits), that'd be bad. But it really depends on your app.Optime
@JoshuaBell Thank you. I think clearing all the stores may be the only choice. Because we can't manually resolve conflict for too many versions. But besides it, we can upgrade the critical user informationWehner
B
2

I develop commercially used apps for business enterprises and when I came across your question I chuckled. Funny how this was asked more than 6 years ago.

I happened to be in a situation where a client needed a new feature on the server’s database and that lead us to add this to the database on the client too. This meant we couldn’t do without the version number in question. We had to specify a higher database version number for the new app release to let the browser know to simply migrate the database to the new version and still keep old user data this time migrating and updating the schema previously written rather than deleting and re- initializing a whole new database.

Beitris answered 3/10, 2022 at 5:35 Comment(0)
K
1

Because the indexedDB database is not fully under the sole control of the developer, this can happen:

The case when the user has multiple tabs (or windows ) open of the same site.

Since all tabs are using the same underlying database, there is a possibility that a user when opening the new tab of the same site receives the new version of the application (just pushed to production) and that version brings changes to the database schema.

When that happens, the new tab has a newer version of the database... and code running in the new tab (since this is the newest version of the application) is made to work with the new DB schema. However, in the previous tab, an old version of the code works with different DB schema - and if we leave that code running it can corrupt the database.

Luckily creators of the indexedDB foresaw this problem and gave us some tools to handle such conflicts - one of which is the version number.

That's why it exists.

Also, this O'Reilly excerpt advises that another reason for the version numbering scheme in IndexedDB API is to be able to store multiple versions of data within the same object store within the same database. However, as the article points out, this is overkill; just reassign your IndexedDB database version.

https://dev.to/ivandotv/handling-indexeddb-upgrade-version-conflict-368a

Kemerovo answered 27/4, 2023 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.