當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


erlang transaction(Fun)用法及代碼示例

transaction(Fun) -> t_result(Res)
transaction(Fun, Retries) -> t_result(Res)
transaction(Fun, Args :: [Arg :: term()]) -> t_result(Res)
transaction(Fun, Args :: [Arg :: term()], Retries) ->
 t_result(Res)
類型:
Fun = fun((...) -> Res)
Retries = integer() >= 0 | infinity

將帶有參數 Args 的函數對象 Fun 作為事務執行。

事務內部執行的代碼可以由一係列表操作函數組成。如果由於用戶錯誤或某個表不可用而導致事務內部出現問題,則整個事務將終止,並且函數 transaction/1 返回元組 {aborted, Reason}

如果一切順利,則返回 {atomic, ResultOfFun},其中 ResultOfFunFun 中最後一個表達式的值。

如果存在結構 {family, Father, Mother, ChildrenList} ,則向數據庫添加族的函數可以編寫如下:

add_family({family, F, M, Children}) ->
    ChildOids = lists:map(fun oid/1, Children),
    Trans = fun() ->
        mnesia:write(F#person{children = ChildOids}),
        mnesia:write(M#person{children = ChildOids}),
        Write = fun(Child) -> mnesia:write(Child) end,
        lists:foreach(Write, Children)
    end,
    mnesia:transaction(Trans).

oid(Rec) -> {element(1, Rec), element(2, Rec)}.

此代碼將一組人員添加到數據庫中。在一個事務中運行此代碼可確保將整個係列添加到數據庫中,或者整個事務終止。例如,如果最後一個子文件格式錯誤,或者執行進程在執行係列代碼時由於 'EXIT' 信號而終止,則事務將終止。因此,絕對不可能出現增加半個家庭的情況。

如果多個進程同時更新相同的記錄,那麽在事務中更新數據庫也很有用。例如,函數raise(Name, Amount)Amount添加到一個人的工資字段中,實現如下:

raise(Name, Amount) ->
    mnesia:transaction(fun() ->
        case mnesia:wread({person, Name}) of
            [P] ->
                Salary = Amount + P#person.salary,
                P2 = P#person{salary = Salary},
                mnesia:write(P2);
            _ ->
                mnesia:abort("No such person")
        end
    end).

當此函數在事務內執行時,運行在不同節點上的多個進程可以同時執行函數raise/2,而不會互相幹擾。

由於 Mnesia 檢測到死鎖,事務可以重新啟動任意次數,因此 Fun 不應有任何副作用,例如等待特定消息。此函數嘗試重新啟動的次數與 Retries 中指定的次數相同。 Retries 必須是大於 0 的整數或原子 infinity ,默認為 infinity 。 Mnesia 使用 exit 異常來表示事務需要重新啟動,因此 Fun 不得以 {aborted, term()} 為原因捕獲 exit 異常。

相關用法


注:本文由純淨天空篩選整理自erlang.org大神的英文原創作品 transaction(Fun) -> t_result(Res)。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。