私はmnesiaテーブルに同じ3つのレコードを挿入/更新する5つのプロセスがあります。これらの各プロセスは、単一のトランザクション内で挿入/更新を行います。Mnesia:予期せずに中断された循環トランザクション
私はこれらの全く同じ3つのレコードを1つのトランザクション内で読み取る5つのプロセスを持っています。
マルチレコードトランザクションの一部としてテーブル全体をロックしない限り、{aborted、{cyclic、node ....}}エラーが発生します。私の直感は、私のユースケースは普通であり、それ自体が中断されたトランザクションを引き起こしてはならないということです。誰かが私の骨頭思考で私を助けることができますか?私がやっているのは、1つのトランザクションで複数の行をキャッシュ(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.
だから、助けてくれてありがとうが、これは正しいとは思わない。 (私はあなたの提案を試みたが、うまくいかなかった)。 Transactional_execute/1はネストされたトランザクションを作成すべきではありません。これは特に停止するように設計されています。コードをトレースするとmnesiaを呼び出すように見えます:sync_transactionは一度だけです。また、複数の挿入プロセス(上記のコード)を繰り返し実行しても何の問題もありません。複数の読み込みプロセス(複数の読み込みプロセスと同じコードを実行する場合は、/insert the value。他のアイデア? – Jr0
実際には、私は* insert *プロセスを単独で実行することでそれを打破することができます。トランザクションの実行コード/ 1が一度呼び出されたことを保証するコードをリファクタリングしました。 )そしてまだそれは壊れている – Jr0
**ホリー・クラップ!**私はそれが私の試みかもしれないと思う...sc:store関数を取り囲む私がそれらを取り除くと、すべてが機能します....私は、試行錯誤の中でそれらの機能を取り囲むことによって、記憶媒体の再試行/デッドロック回避を傍受している可能性がありますか? – Jr0