F=fun()->
case is_username_available(User) of %% does a mnesia:read to see if
there is a record with that username
false -> throw(username_in_use);
true -> mnesia:write(User)
end,
mnesia:transaction(F).
Don't I have a potential race condition here? Since there is no record
to lock because it doesn't exist, how can mnesia guarantee another
process isn't also going to write that same Username to the database?
If I'm doing this wrong, what's the right way? A table lock (eww)?
My second question is regarding a quote from the mnesia manual:
"Write locks are normally acquired on all nodes where a replica of the
table resides (and is active). Read locks are acquired on one node
(the local one if a local replica exists). "
What does it mean read locks are acquired on one node? What would
happen when a table is distributed? Wouldn't that defeat the purpose?
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://www.erlang.org/mailman/listinfo/erlang-questions
> If I wanted to check if a username is in use before registering an
> account like this:
>
> F=fun()->
> case is_username_available(User) of %% does a mnesia:read to see if
> there is a record with that username
> false -> throw(username_in_use);
> true -> mnesia:write(User)
> end,
>
> mnesia:transaction(F).
>
> Don't I have a potential race condition here? Since there is no record
> to lock because it doesn't exist, how can mnesia guarantee another
> process isn't also going to write that same Username to the database?
> If I'm doing this wrong, what's the right way? A table lock (eww)?
You could use a gatekeeper - a singleton process on only one node which is allowed to create usernames. Creators make a request to the gatekeeper which serialises the requests and therefore prevents the race. The problem then shifts to process registration consistency and takeover in the case of the gatekeeper failure.
Sharding/splitting the gatekeeper responsibility by eg. username first letter would quarantine the damage from a gatekeeper failure.
> My second question is regarding a quote from the mnesia manual:
> "Write locks are normally acquired on all nodes where a replica of the
> table resides (and is active). Read locks are acquired on one node
> (the local one if a local replica exists). "
>
> What does it mean read locks are acquired on one node? What would
> happen when a table is distributed? Wouldn't that defeat the purpose?
A read lock on any node prevents a write lock from being acquired on that item.
A write lock must be acquired on *all* nodes so it is sufficient to take a read lock on any one node to block a write lock from being acquired.
--
Rich
Enjoy a safer web experience. Upgrade to the new Internet Explorer 8 optimised for Yahoo!7. Get it now.
If NodeA and NodeB both have replicas of the table containing the
balance, couldn't this happen:
NodeA reads balance of 5
NodeB reads balance of 5
NodeA writes balance of 10
NodeB writes balance of 15
Since there is no read lock on each node? I'm assuming it would work
like this because, if I understand correctly, the locks are acquired
AS the transaction processes, and not the second the transaction fun
is executed, right?
In this situation, is the solution to simply just grab a write lock on
the record when reading it?
This poses another question: how do you acquire a write lock on a
record when you do an index read?
> erlang-questi...@erlang.orghttp://www.erlang.org/mailman/listinfo/erlang-questions
Actually, no. Mnesia waits for the locks needed before
proceeding, and keeps the locks until it either aborts
or commits. However, in any locking environment, one
must guard against deadlocks. If the lock manager is
centralized, it's possible to maintain a wait-for graph,
which is scanned each time a new lock is requested.
This approach doesn't scale in a distributed setting,
so an alternative approach, called "deadlock prevention",
is to allow only unidirectional dependencies (for some
definition of unidirectional - e.g. from smaller to
larger pids.) If a lock is requested that would create
a dependency in the other direction, one of the
transactions involved is restarted. This is why mnesia
transactions can restart sometimes.
BR,
Ulf W
--
Ulf Wiger
CTO, Erlang Training & Consulting Ltd
http://www.erlang-consulting.com
BR,
Ulf W
-- originalmedd. --
Ämne: Re: [erlang-questions] Couple of questions about mnesia locking
Från: Ryan Lepidi <rye...@gmail.com>
Datum: 2009.04.05 19.51
_______________________________________________