On Oct 13, 9:51 pm, jim <[EMAIL PROTECTED]> wrote:
> Rich,
>
> I've been working with refs tonight and I appreciate the validate-fn
> addition.  Makes my life a lot easier.
>
> From reading the docs, 'ensure' keeps a ref from changing inside a
> dosync.  But if accesses to refs are contained in function calls that
> are called during the transaction, the programmer might overlook them
> when writing the dosync.
>
> A hack I came up with to deal with this is to bind a new value to
> 'deref' that saves the ref to a list before calling the normal deref
> function.  Then as a final step in the transaction, to go through the
> list of deref'd refs and call 'ensure' on each one.
>
> Do you have any thoughts on how to handle the situation better?
>

Yes - don't do it!

First, let me explain ensure a bit more. When running in a
transaction, you will see the ref world as-of a point in time,
entirely consistent. Refs never change inside a dosync unless you
change them. This is known as snapshot isolation, and, under MVCC, is
an efficient and robust way to do things. Reads don't need to be
tracked, and consistency is good. In most cases, you only care that
the refs you are writing to haven't changed before you commit - this
is done automatically by the transaction.

ensure is there to, well, ensure that a ref >that you've only read< is
no different when your transaction commits. When would you want to do
this? - when your business rule has an invariant on read data. Failing
to lock down the invariant read items in this case risks what is
called a write skew. A classic example is a financial program that
lets you have two accounts, at most one of which can run a negative
balance. Any debit to an account will change only that account, but
read and rely upon the value in the other account not changing. In
some MVCC systems you'd have to issue a dummy write to the other
account in order to get it to participate in the transaction. ensure
is just a cleaner, clearer way to do this.

Why wouldn't we want to ensure all reads? For two reasons - one, it's
terribly inefficient, and two, that's not the way the concurrent world
works. In the real world we make an observation, make a decision, and
act, and the world doesn't stop in the meantime. Physics keeps actions
from conflicting, and, similarly, MVCC transactions prevent write
conflicts.

You're seeing more and more assaults on transactional DBMS systems not
being able to scale, people accepting eventual or partial consistency
etc. I think some of these problems stem from a stop-the-world
approach, one that we have to question in our in-memory designs as
well.

Many STMs do read tracking and ensure that nothing you've read has
changed during the transaction. They also may keep track of each ref
only from the point in time you first read it, offering no whole-world
consistency at all. I think MVCC is a better approach.

As an example, consider a program like one that needs to give all
salespeople that have made their quota a bonus. The program will need
to read the quotas and sales, and will change their paycheck. By doing
so in a Clojure transaction, it is making decisions based upon
consistent data. There's no reason to stop people from selling in the
meantime, concurrently, i.e. you don't care if, at the end of issuing
bonuses, more sales have occurred.

It will be possible for me to add an optional ensure-all mode to the
transactions if there is sufficient demand, but I encourage you to
first understand and rely upon the substantial consistency guarantees
and efficiencies offered by Clojure's MVCC snapshot isolation, using
ensure only when you have a true read invariant/write skew situation.

Rich


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To post to this group, send email to clojure@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to