<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:times new roman,new york,times,serif;font-size:12pt"><div>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. <br><br>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.)<br><br>Best,<br>Thomas<br></div><div style="font-family: times new roman,new york,times,serif; font-size: 12pt;"><br><div style="font-family: times new roman,new york,times,serif; font-size: 12pt;"><font face="Tahoma" size="2"><hr size="1"><b><span style="font-weight: bold;">From:</span></b> Ryan Lepidi <ryeguy1@gmail.com><br><b><span style="font-weight: bold;">To:</span></b> Ulf Wiger <ulf.wiger@erlang-consulting.com><br><b><span style="font-weight: bold;">Cc:</span></b> erlang-questions@erlang.org<br><b><span style="font-weight: bold;">Sent:</span></b> Sunday, April 5, 2009 7:53:25 PM<br><b><span style="font-weight: bold;">Subject:</span></b> Re: [erlang-questions] Couple of questions about mnesia locking<br></font><br>
I apreciate your guys' help. I have a question though, what would happen in this situation?<br><br>NodeA reads balance of 5; gets read lock on record<br><br>
NodeB reads balance of 5; gets read lock on record %on another node, so read lock is possible<br>
NodeB writes balance of 15; gets write lock on record %does the write then releases the lock<br><br>
NodeA writes balance of 10; gets write lock on record<br><br>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?<br>
<br>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?<br>
<br><div class="gmail_quote">On Sun, Apr 5, 2009 at 3:27 AM, Ulf Wiger <span dir="ltr"><<a rel="nofollow" ymailto="mailto:ulf.wiger@erlang-consulting.com" target="_blank" href="mailto:ulf.wiger@erlang-consulting.com">ulf.wiger@erlang-consulting.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="im">Hynek Vychodil wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
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.<br>
</blockquote>
<br></div>
Actually, no. Mnesia waits for the locks needed before<br>
proceeding, and keeps the locks until it either aborts<br>
or commits. However, in any locking environment, one<br>
must guard against deadlocks. If the lock manager is<br>
centralized, it's possible to maintain a wait-for graph,<br>
which is scanned each time a new lock is requested.<br>
<br>
This approach doesn't scale in a distributed setting,<br>
so an alternative approach, called "deadlock prevention",<br>
is to allow only unidirectional dependencies (for some<br>
definition of unidirectional - e.g. from smaller to<br>
larger pids.) If a lock is requested that would create<br>
a dependency in the other direction, one of the<br>
transactions involved is restarted. This is why mnesia<br>
transactions can restart sometimes.<br>
<br>
BR,<br>
Ulf W<br><font color="#888888">
-- <br>
Ulf Wiger<br>
CTO, Erlang Training & Consulting Ltd<br><span>
<a target="_blank" href="http://www.erlang-consulting.com">http://www.erlang-consulting.com</a></span><br>
</font></blockquote></div><br>
</div></div></div><br>
</body></html>