[erlang-questions] Couple of questions about mnesia locking

Thomas Lindgren thomasl_erlang@REDACTED
Mon Apr 6 19:55:59 CEST 2009

Your question has more to do with transactional systems in general than mnesia. Your example is not "serializable" and so wouldn't be permitted in a transactional database. As far as I can see, NodeA and NodeB would instead deadlock, and one of them would be aborted and perhaps retried. 

Regarding how this is implemented (though perhaps mnesia does things differently), before acquiring a write lock on the balance record, NodeB would first have to wait for NodeA to release its read lock on the same, and conversely, NodeA would wait for all read-lockers of the record to release their locks before acquiring its write lock. A simple way of getting things right is for a transaction to only releases its locks when it commits or aborts. (It's up to the database to detect and repair deadlocks.)


From: Ryan Lepidi <ryeguy1@REDACTED>
To: Ulf Wiger <ulf.wiger@REDACTED>
Cc: erlang-questions@REDACTED
Sent: Sunday, April 5, 2009 7:53:25 PM
Subject: Re: [erlang-questions] Couple of questions about mnesia locking

I apreciate your guys' help. I have a question though, what would happen in this situation?

NodeA reads balance of 5; gets read lock on record

NodeB reads balance of 5; gets read lock on record   %on another node, so read lock is possible
NodeB writes balance of 15; gets write lock on record %does the write then releases the lock

NodeA writes balance of 10; gets write lock on record

NodeA would have a stale value and NodeB would not have to wait for any locks, so neither of them would restart afaik. I know one way to prevent this is to acquire a write lock at the beginning, but how can you do that with an index_read? It seems the only way to do that would be to read the object then wread() it again with the object's primary key. Blech. Hopefully there is some other solution?

Actually, after reading Ulf's reply, I just realized what I typed is probably answered by what he said. Do you mean ALL locks are acquired before any records are read or written? So in other words, the situation above is impossible?

On Sun, Apr 5, 2009 at 3:27 AM, Ulf Wiger <ulf.wiger@REDACTED> wrote:

Hynek Vychodil wrote:

mnesia uses optimistic locking. When NodeB's write is called than transaction fails and is restarted. This is why mneasia transaction should not contain side-effects. See mnesia manual for details.

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.

Ulf W
Ulf Wiger
CTO, Erlang Training & Consulting Ltd

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20090406/f8619145/attachment.htm>

More information about the erlang-questions mailing list