[erlang-questions] Couple of questions about mnesia locking

Richard Andrews <>
Sat Apr 4 13:31:26 CEST 2009






> 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.



More information about the erlang-questions mailing list