Unintentionally intercepting Mnesia's transact

2019-02-27 03:35发布

问题:

So, I was having all kinds of trouble with CRUD operations on sets of records in one transaction. It lead me to post 2 questions here, Trouble and MoreTrouble. However, I think that both those issues where created by the following: Within my transactions, I enclosed my mnesia:writes, reads, etc. in try/catch blocks that caught everything including mnesia's aborted transactions as part of its deadlock avoidance algorithm. I.e.,

insert(Key, Value) ->
   F = 
      fun() ->
         case sc_store:lookup(Key) of
           {ok, _Value}       -> sc_store:replace(Key, Value);
           {error, not_found} -> sc_store:insert(Key,Value)
         end
       end,
   try
      case mnesia:transaction(F) of
         {atomic, Result}  -> Result;
         {aborted, Reason} -> ...
      end
    catch
        Error:Reason -> ...
    end

end

sc:lookup/1, for example, looked like this:

lookup(Key) ->
   try 
      case mnesia:read(key_to_value, Key) of
         [#key_to_value{type = Type, scope = Scope, value = Value}] -> 
            {ok, {Value, Type, Scope}};
         []                       -> 
            {error, not_found}
      end
   catch
      _Err:Reason -> {error, Reason}
   end.

I think I must have been "intercepting" / catching mnesia's dead-lock avoidance algorithm instead of letting it retry as designed.

Is that possible? If so, its a (&^& of a gotch-a for a newbee like me. If not, any ideas why this code produced so many problems for me, but removing the try/catch from the mnesia:read, etc. functions cleared up all of my problems?

回答1:

Yes, I'm not sure if that's properly documented anywhere, but you should not mask out the exceptions in mnesia operations. If you do that, it looks to mnesia like your transaction fun worked as intended, even though some operations actually didn't work at all.



标签: erlang mnesia