Discussion:
use CFLOCK within CFTRANSACTION, or not?
(too old to reply)
Conanicut
2006-01-31 03:58:17 UTC
Permalink
This Macromedia article
http://www.macromedia.com/devnet/coldfusion/articles/cftransaction.html does a
good job of explaining transactions, but I'm confused by the 3rd-to-last
paragraph, which begins by referencing a Macromedia tech note
http://www.macromedia.com/cfusion/knowledgebase/index.cfm?id=tn_17000. The tech
note advises using CFLOCK inside CFTRANSACTION in the case of getting a newly
inserted ID number from a table. But the article says you don't need to do
this, and that the only way to be 100% sure of getting the correct ID number is
to specify a serializiable isolation level transaction in a CFTRANSACTION tag,
but says best practices discourage doing this! About using CFLOCK inside
CFTRANSACTION, as the tech note recommends, the article says: "This isn't
completely true because other applications that access the data will not obey
the lock, nor will any other queries that ColdFusion executes obey the lock
since they are not contained within the same named cflock." I don't understand
this -- it couldn't mean that other queries with the same named lock won't obey
the lock, could it? What would be the use of locks at all, then? How do people
handle the locking/transaction issue? Thanks.
BKBK
2006-01-31 12:39:47 UTC
Permalink
it couldn't mean that other queries with the same named lock won't obey the
lock, could it?
That is in fact what Simon Horwith means in the last but two paragraph of
http://www.macromedia.com/devnet/coldfusion/articles/cftransaction.html.
Transaction tag or no transaction tag, a thread will stop at a named lock only
if the thread itself is coming from a lock of the same name. Otherwise, it will
just run the code in the lock.
What would be the use of locks at all, then?
It is commonly known that there are 3 types of shared data, namely data in the
scopes session, application and server. The data is called "shared" because
different requests from a client may share the same session, different sessions
may share one application and different applications may share one server.
However, I consider there to be a fourth type of shared data. It is the data
defined in a named lock. Take the following named lock, for example:

<cflock name="myLock1" type="EXCLUSIVE" timeout="5">
<cfset Variables.myVarX="#x#">
<cfset Variables.myVarY="#myFunction(Variables.myVarX)#">
</cflock>

I think we may interprete myLock1 as a user-defined shared-data scope.
However, any two arbitrary threads may run the code in the lock. So, what's the
point in locking it, if the lock will not ensure the integrity of the shared
data?

As it stands, the concept is incomplete. To complete it, we have to borrow an
idea from the familiar scopes. Just as the name of a session, application or
server variable must always be preceded by its scope, so, too, any code that
involves the variables myVarX and myVarY must always occur within a lock named
myLock1. That completes the concept of a named lock as shared-data scope.

To illustrate, an exclusive lock on session scope causes all other threads
from the session scope to wait in a queue until the lock is released. By
analogy, the exclusive lock named myLock1 causes all other threads from a lock
named myLock1 to wait in a queue until the present myLock1 is released. Suppose
Coldfusion is busy running myFunction(Variables.myVarX) when another thread,
e.g. from myOtherFunction(), starts executing the following code

<cfset Variables.notMyVarX="#x2#">
<cfset Variables.notMyVarY="#y2#">

<cflock name="myLock1" type="READONLY" timeout="5">

<cfif isDefined("Variables.myVarX")>
<cfset myFinalVarX="#Variables.myVarX#">
<cfset myFinalVarY="#Variables.myVarY)#">

<cfelseif isDefined("Variables.notMyVarX")>
<!--- Undesired result --->
<cfset myFinalVarX="#notMyVarX#">
<cfset myFinalVarY="#notMyVarY#">
</cfif>

</cflock>

Then the thread will wait for the exclusive lock on myFunction() to be
released. Without the second lock (of same name), it wouldnit wait and we would
get the undesired result.

The morale is clear. You can prevent race conditions for variables within a
named lock, only if you apply a lock of the same name whereever those variables
occur in the application.

How do people handle the locking/transaction issue?
There are 2 major distinctions between cflock and cftransaction. First, cflock
applies to Coldfusion code, whereas cftransaction applies to database
operations. Second, cflock's functionality is "make operation x wait till
operation y finishes, whereas cftransaction's is "complete both operation x and
operation y together or do neither". The lock that cftransaction's
isolation-attribute enforces applies to the database server, not to Coldfusion.
So, use cflock to prevent race conditions in shared data, e.g. to prevent one
thread from reading a Coldfusion variable while another is writing to it; use
cftransaction to instruct the DBMS to run multiple queries as one single
transaction. Use the isolation attribute instruct the database engine what kind
of lock it should impose during the transaction.
Conanicut
2006-02-01 19:23:38 UTC
Permalink
Thank you for your very helpful post, BKBK. As soon as my webhost upgrades to
the latest MySQL I can get into stored procedures -- sounds like the best route
overall. I appreciate your careful response, thanks again.

Loading...