Notice: This concern has been resolved as of CF 5 and is no longer an issue.

Why you should use CFLOCK around any Verity tags, or how two tags on the same page can run at the same time


(This article is a actually an extended discussion of a tip listed in tip archive VI.)

This question is similar to, but different from, two related tips also offered here, on Why application.dsn is bad and Do I really need to lock access to shared scope variables?. Be sure to check those out as well.

Last updated: June 28, 2001

This will continue to be expanded and refined and soon offered as an article in the ColdFusion Developers Journal or the Allaire DevCenter. Your comments are welcome.

Are you experiencing strange server hangs that you can't explain? There are plenty of possible reasons (see this very long, ongoing Macromedia forum thread for more discussion about that.)

Here's something else useful that I want to report to readers on that forum thread. I just made a discovery that verity index processing could be a source of server hangs. Even if you don't use verity, what I came to realize may still be of value to you, if you haven't already made the some realization. Also, if you thought CFLOCK was only useful for locking shared scope variable access, think again.

Problems doing two potentially conflicting index operations on the same page

What I found was that running a template with a CFCOLLECTION tag to purge a verity collection (index), followed on the same page by a CFINDEX to populate the index, caused the server to hang. It only took a minute for me to realize, holy cow!, we presume tags like this run in sequence, with one running after the other finishes, synchronously, but that's not guaranteed at all. ColdFusion's a multi-threaded service. It could be doing two things at once, even as requested by different tags on the same page.

Indeed, when I thought to throw a CFLOCK around each (with an exclusive on each, because both were update operations and giving them the same name as each other, using the name of the collection), the problem never recurred. That proved to me, at least, that my theory was true. CF, being a multi-threading process, was moving on to the next tag (to populate the collection) while the thread for the first one was still purging the collection. Wow!

Now if you're thinking "big deal", is that because you already understood the ramifications of this? Or because you don't use verity indexing? Or you do but you don't think these two tasks being executed on the same page is that common? So none of this is related to your server?

Bigger than Just Verity Indexing

Hold on there, bucko. The implications of this are substantial, I think: forget about verity indexes. Think about any kind of similar process that might run within the cf server where this sort of contention could be problematic. Database queries aren't an issue, since they run in a separate process. But there could be other things (any ideas?).

The point is, people often talk about CFLOCK for locking shared scope variable access, but it's equally important to prevent any kind of concurrent access to something being written to while it's being either read or written to by another process within the server.

And it's certainly not even just about things going on within a single page. If the processes were in different pages (which might be even harder to track down and observe), the result is the same (although the odds could be less that two such things would run concurrently).

Two consecutive tags on a page actually running concurrently

But to me, the bigger realization was that two tags on the same page might run concurrently despite their appearing one after another.

Going back to the verity example, it's certainly reasonable for someone to do these two kinds of collection mgt tasks on the same page (purge and re-index, or optimize and update, or even delete/create/re-index).

If you think about it, the same would be true if you simply did a CFINDEX to populate an collection followed by a CFSEARCH to query it. The search may try to take place while the update of the collection is still running. I imagine this sort of thing is done all the time, especially by folks just getting started with this (which might explain the random occurrences of server lockups that some experience).

Solution: Lock all references to code doing verity index processing

So the key, at a minimum, is to lock all references to verity collections. Put a readonly lock around cfsearch tags, and an exclusive lock around cfindex and cfcollection tags, and give the lock a NAME equal to the name of the collection (the scope attribute is irrelevant to this issue, we want to prevent two index operations on the same collection from running if either is doing an operation that would conflict with the other). By setting the lock's name to the name of the collection, and using the correct TYPE of lock for each operation (exclusive on writes, readonly on reads) we achieve that while also not causing or encountering locks with processes working on another collection.

It would seem the administrator ought also to put locks around its use of these tags, executed on the users behalf via the admin interface, and it ought to use the same logic for the name.

Indeed, this points up something else very important: this sort of lock resolution is an all or nothing thing. All references to the collection, both searches and update processes, must be locked this way. If even a single template runs a search or update against a given collection without a lock, and another template that does lock coincidentally starts up at the same time doing a conflicting process against that collection (doing an update when the unlocked task has started a search or other update, or doing a search when the unlocked task has started another update), the potential for conflict will exist.

Timeout Time

As for the timeout time, that's a little hard to gauge. It really depends on the size of your collection, the nature of the operation being done, the frequency with which potentially competing operations take place--and of course, how long they tend to take. Just remember: the timeout isn't about the time it takes to do the thing being locked: it's the time that thing is willing to wait to get a needed lock. If an update starts when a search or other update is running, or if a search starts while an update is running, and the other operation doesn't finish within the timeout time specified for the operation being started, that "blocked" operation will experience the timeout.

Read Locks Don't Block Each Other

Finally, lest anyone misconstrue things, the fact that two index search operations (CFSEARCH tags) are locked readonly does NOT keep them from running concurrently. It only keeps them from running when a locked update process is running, or keeps any locked update from starting while they are running. This should have no impact on performance, at least from the standpoint of an assertion that it would single-thread searches. It would not.

Conclusion

I find that people often misunderstand these aspects of locks, so pardon the "lecture". Those who know me realize that it's my style, and you can bet that this will make it into an article, user group talk, or class (or all 3). It's already in a chapter for an upcoming book: which is how I came upon the realization--nothing like writing about a subject to force you to pay attention to details you'd never noticed before!

I've offered it here because I wonder if other people will be equally surprised by the realization, especially about two tags running one after another in the same template but executing concurrently due to multi-threading. And if you weren't as familiar with locks, maybe you are now!

I had just one last thought: you may be thinking you don't need to bother locking your CFSEARCH tags for a given collection because you know it's never updated, or only updated overnight, etc. While it's certainly true that if you could guarantee that no one would ever be updating a given verity collection while attempting to search it(and vice-versa), then locks around the CFSEARCH tags would not be needed. But there's really no way to guarantee this. Also, there's no performance penalty for locking your searches, so why take the risk?

Of course, there is one way that this problem could go away entirely: if the tags had built-in locking. I suppose that's the ultimate solution. Maybe Macromedia has or will consider it.

Still, if the discussion has taught you something about locking, or about considering when two tags on the same page can run concurrently and be in conflict, then your time spent reading this (and my time spent writing it) has been well spent.

/charlie

Was this article useful to you? Do you disagree with anything? Please let me know

Tips Contents:

| Home | ColdFusion | Articles | Presentations
| User Groups | Other Resources | Press Releases | Company

© 1998-2024, Charles Arehart, SysteManage
Our Practice Makes You Perfect