I have 5 processes that insert / update the same 3 entries in the mnesia table. Each of these processes performs its insertions / updates in a single transaction.
I have 5 more processes that read these 3 records, also within the framework of one transaction.
If I lock the entire table as part of a multi-record transaction, I get {aborted, {circular, node ....}}. My intuition is that my use case is common and should not in itself lead to an aborted transaction. Can someone help me with my bone thinking? All I do is insert (or read) multiple lines in the cache (mnesia table) in one transaction.
The insertion of the three entries looks like this:
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.
sc_store: replace, insert and search look like this:
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.