У меня есть 5 процессов, которые вставляют / обновляют те же 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.
sc_store: замена, вставка и поиск выполняются следующим образом:
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.