[erlang-questions] (not) understanding mnesia transactions
Dan Gudmundsson
dgud@REDACTED
Thu Jun 18 12:05:53 CEST 2009
The problem here lies in how mnesia handles indexes and locks on indexes.
If you remove the index the code works as expected.
Except for io:format("Expecting ~p~n", [lists:seq(1, 10)]), which is wrong,
since you use dirty_update_counter which will be invoked
several times when there is a lock conflict on the write lock.
But back to the index lock problem.
Whether you use qlc or index_read in that query the same code will be invoked.
mnesia:index_read grabs a read lock on the rows it hits.
In your case when 5 parallel processes read the index for "url-1"
none is found, no locks are grabbed.
You then generate a unique key for each process, and write the record down,
that will succeed since they have unique keys.
This is bug in mnesia, 12 years old :-(
/Dan
Seth Falcon wrote:
> Chandru,
>
> Thanks for the explanation.
>
> * On 2009-06-17 at 23:57 +0100 Chandru wrote:
>> Your code works as you expect it to if you first acquire a write
>> lock on the table before you read from it.
>
> Yes, that seems to fix it.
>
>> So all your clients acquire read locks, decide that a record for a URL does
>> not exist, and create a record. I'm not sure what locks are acquired for
>> records which do not exist. I'm sure the answer lies in reading the mnesia
>> source code...
>
> Makes some sense. I guess the big piece that I was missing is that
> transactions can run concurrently and the programmer needs to manage
> the locking. A more subtle point, is that the locking mechanism is
> such that once a lock is aquired it is kept for the remainder of the
> transaction (I think).
>
> So in the following example from the mnesia man page, the call to
> mnesia:wread has the same effect as calling mnesia:lock and then
> mnesia:read.
>
> raise(Name, Amount) ->
> mnesia:transaction(fun() ->
> case mnesia:wread({person, Name}) of
> [P] ->
> Salary = Amount + P#person.salary,
> P2 = P#person{salary = Salary},
> mnesia:write(P2);
> _ ->
> mnesia:abort("No such person")
> end
> end).
>
>
> ________________________________________________________________
> erlang-questions mailing list. See http://www.erlang.org/faq.html
> erlang-questions (at) erlang.org
>
More information about the erlang-questions
mailing list