Mnesia:意外中止,循环事务

Jr0*_*Jr0 3 erlang mnesia

我有 5 个进程在 mnesia 表中插入/更新相同的 3 条记录。这些进程中的每一个都在单个事务中执行其插入/更新。

我还有 5 个其他进程读取这些相同的 3 条记录,也在一个事务中。

除非我将整个表锁定为多记录事务的一部分,否则我会收到 {aborted, {cyclic, node....}} 错误。我的直觉是,我的用例是普通的,其本身不应该导致事务中止。有人可以帮助我解决我愚蠢的想法吗?我所做的只是在一个事务中的缓存(mnesia 表)中插入(或读取)多行。

插入 3 条记录如下所示

insert_keylist(Keys) ->  
    F = fun() -> insert_iter(Keys) end,  
    transactional_execute(F).

insert_iter([]) ->
    ok;
insert_iter([{Key, Value} | KVs]) ->
   insert(Key, Value),
   insert_iter(Kvs).

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,
  transactional_execute(F).    


transactional_execute(F) ->
    case mnesia:is_transaction() of
       true -> F();
       false ->
           try mnesia:sync_transaction(F) of
               {atomic, Result}   -> Result;
               {aborted, Reason}  -> {aborted, Reason}
           catch
                ErrorCl:Error     -> {error, {ErrorCl, Error}}
        end
     end.
Run Code Online (Sandbox Code Playgroud)

sc_store:replace、insert和lookup如下:

replace(Key, Value) ->
    try
       case mnesia:wread({key_to_value, Key}) of
          [#key_to_value{} = Rec] -> 
            mnesia:write(Rec#key_to_value{value = Value});
          []                       -> 
        {error, not_found}
        end
    catch
       _Err:Reason ->
         {error, Reason}
    end.

insert(Key, Value, Type, Scope, TTL, TTLMessage, Ref) ->
   try
      NowDT = calendar:now_to_datetime(erlang:now()),
      ok = mnesia:write(#key_to_value{key = Key, 
                type = Type,
                scope = Scope,
                value = Value,
                create_time_dt = NowDT,
                ttl_secs = TTL,
                ttl_message = TTLMessage,
                ref = Ref})
   catch
      _Error:Reason ->
        {error, Reason}
   end.

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.
Run Code Online (Sandbox Code Playgroud)

Jr0*_*Jr0 5

实际上,问题是事务中使用 try/catch 围绕 mnesia 操作。请参阅此处了解更多信息。