Welcome to Objectivity, Inc. -- makers of the industry leading Objectivity/DB object-oriented database management platform, Grid Certified (Levels 1 through 6), and SOA compliant Twitter LinkedIn YouTube RSS Feed

.

Saturday, November 7, 2009

Lock Granularity

Performance is always an issue and perhaps the most visible trade-off was the decision to lock bunches of objects rather than individual objects. In an Objectivity/DB federation that translates to locking at the container level rather than the object level. Doing that dramatically reduces the number of lock requests. However, there's a potential downside - a long running update transaction could prevent other clients from reading the objects in the containers it is updating.

The solution was quite simple and it exploits the underlying shadow page recovery mechanism. When you start updating a transaction the Objectivity/DB Storage Manager, a major component of the kernel, creates a new version of the container. Updates and new objects are written to new physical pages. The old ones are untouched until the commit occurs. The introduction of the Multi-reader, One-Writer (MROW) transaction mode makes it possible for existing or new readers to access the previous version of the container while the new one is being written. In some cases the new version will be rolled back, freeing the old versions for updates by subsequent transactions from any client.

The picture is made slightly more complex because of the need to maintain a consistent view for long running readers. Suppose that process A opens version 1 of a container. Then process B starts updating it, creating version 2. Then process B commits the transaction while A is still running. Process C then opens the container and it sees version 2. That's not a problem unless processes A and C have to collaborate in any way that involves this container, as they are looking at different versions. When process A eventually finishes its transaction there will be two versions of the container, but only the latest one will be picked up by new readers. This mechanism can cause some version creep, with multiple versions of a container existing in the database file. To prevent that being a problem, the kernel deletes the old, not currently accessed, versions as soon as a new updater comes along.

Object server DBMSs generally log individual operations or page updates and lock at the object level. The problem with that approach is that you not only have more lock server traffic, you also run a big risk of deadlocks as clients navigate through complex networks of objects. The subsequent queueing can significantly degrade performance. I was very amused at the recent ICOODB conference to hear an engineer from another ODBMS supplier describing that object level locking within their system data had been causing bottlenecks and limiting server throughput. He then proudly described the system of latches (transient, within transaction locks) and data redesign that had allowed them to defer, but not eliminate the problem. What he was saying, out of the earshot of their sales and marketing people, was that their highly touted object level locking was actually hurting the performance of their server.

Every time that we assembled a list of desired features for new releases in our early days, the sales people would request "Object Level Locking." However, our users were finding that the performance of our distributed MROW implementation was much better than centralized servers with object level locking.

Labels: , ,